diff options
author | Sebastien Roy <Sebastien.Roy@Sun.COM> | 2009-09-22 22:04:45 -0400 |
---|---|---|
committer | Sebastien Roy <Sebastien.Roy@Sun.COM> | 2009-09-22 22:04:45 -0400 |
commit | 2b24ab6b3865caeede9eeb9db6b83e1d89dcd1ea (patch) | |
tree | 72c0d7d4e1c44843a86bab6e3ed6f82cfa7356af /usr/src/lib | |
parent | 51fc88a818087605a0e5f11eddb8b66576f72c23 (diff) | |
download | illumos-joyent-2b24ab6b3865caeede9eeb9db6b83e1d89dcd1ea.tar.gz |
PSARC 2009/373 Clearview IP Tunneling
PSARC 2009/410 Datalink Administration from Non-Global Zones
6858533 Clearview IP Tunneling
4861777 *snoop* cannot snoop on tunnel interfaces
5010680 M_IOCTL interface between ip and tun is horribly wrong
5029727 tun prints bogus debug messages when receiving multicast packets on 6to4 tunnels
6835873 dlpi_walk() silently fails in an exclusive zone
4152864 must not allow two tunnels to have the same tsrc/tdst pair
6855902 link and flow kstats are too promiscuous
6218826 need to be able to tunnel into a zone
4505468 network interface names can confuse, lie, and deceive
4524756 tun_wproc() takes up too much stack
6417373 tun_wproc_mdata assertion failures
4627970 scalability problems with IP in IP tunnels
4674797 ifparse_ifspec() will not correctly parse ipv6 tunnels
6509231 dladm should show links in exclusive stack zone
4793233 tun driver should include addr in DL_PHYS_ADDR_ACK for non-zero lengths
6795831 ZONE_*_DATALINK syscalls should take datalink_id_t as argument
6791472 mac module doesn't allow MAC addresses < 6 bytes
6618091 Race condition trips ASSERT() in tun.c's SIOCSLIFNAME path
6837580 bogus mi_active check in mac_set_mtu()
6868083 libinetutil: ofmt_open()'s template argument should be const
6870313 libdladm: needless dladm_init_linkprop() in i_dladm_aggr_up()
6872221 panic in dls_devnet_close() if "mtu" property is being set
4289774 Change to the interface-id does not change IPv6 link-local address
6873561 unable to create links with 31 character link names
6874666 changing a link property can accidentally destroy it
6874682 removing a link attribute corrupts the attribute list
6875167 IPCL_ISV6 conn flag is set but never used
6881764 itp reference leak in ipsec_construct_inverse_acquire()
6881951 dladm delete-vlan can no longer delete persistent-only VLANs
--HG--
rename : usr/src/uts/common/inet/tun.h => usr/src/uts/common/inet/iptun.h
rename : usr/src/uts/common/inet/ip/tun.c => usr/src/uts/common/inet/iptun/iptun.c
rename : usr/src/uts/intel/tun/Makefile => usr/src/uts/intel/iptun/Makefile
rename : usr/src/uts/sparc/tun/Makefile => usr/src/uts/sparc/iptun/Makefile
Diffstat (limited to 'usr/src/lib')
32 files changed, 1027 insertions, 896 deletions
diff --git a/usr/src/lib/brand/native/zone/config.xml b/usr/src/lib/brand/native/zone/config.xml index 9ede6178dc..31ec5834db 100644 --- a/usr/src/lib/brand/native/zone/config.xml +++ b/usr/src/lib/brand/native/zone/config.xml @@ -77,6 +77,7 @@ <privilege set="default" name="sys_acct" /> <privilege set="default" name="sys_admin" /> <privilege set="default" name="sys_ip_config" ip-type="exclusive" /> + <privilege set="default" name="sys_iptun_config" ip-type="exclusive" /> <privilege set="default" name="sys_mount" /> <privilege set="default" name="sys_nfs" /> <privilege set="default" name="sys_resource" /> diff --git a/usr/src/lib/brand/native/zone/platform.xml b/usr/src/lib/brand/native/zone/platform.xml index 4970516328..0aacc8c401 100644 --- a/usr/src/lib/brand/native/zone/platform.xml +++ b/usr/src/lib/brand/native/zone/platform.xml @@ -89,6 +89,7 @@ <device match="zfs" /> <!-- Devices to create in exclusive IP zone only --> + <device match="dld" ip-type="exclusive" /> <device match="icmp" ip-type="exclusive" /> <device match="icmp6" ip-type="exclusive" /> <device match="ip" ip-type="exclusive" /> @@ -104,6 +105,7 @@ <device match="ipsecesp" ip-type="exclusive" /> <device match="ipstate" ip-type="exclusive" /> <device match="ipsync" ip-type="exclusive" /> + <device match="iptunq" ip-type="exclusive" /> <device match="keysock" ip-type="exclusive" /> <device match="rawip" ip-type="exclusive" /> <device match="rawip6" ip-type="exclusive" /> diff --git a/usr/src/lib/brand/sn1/zone/config.xml b/usr/src/lib/brand/sn1/zone/config.xml index c32690afcf..ba458e719e 100644 --- a/usr/src/lib/brand/sn1/zone/config.xml +++ b/usr/src/lib/brand/sn1/zone/config.xml @@ -71,6 +71,7 @@ <privilege set="default" name="sys_acct" /> <privilege set="default" name="sys_admin" /> <privilege set="default" name="sys_ip_config" ip-type="exclusive" /> + <privilege set="default" name="sys_iptun_config" ip-type="exclusive" /> <privilege set="default" name="sys_mount" /> <privilege set="default" name="sys_nfs" /> <privilege set="default" name="sys_resource" /> diff --git a/usr/src/lib/brand/sn1/zone/platform.xml b/usr/src/lib/brand/sn1/zone/platform.xml index 2d5fb2eea0..f07bc4eddc 100644 --- a/usr/src/lib/brand/sn1/zone/platform.xml +++ b/usr/src/lib/brand/sn1/zone/platform.xml @@ -93,6 +93,7 @@ <device match="zfs" /> <!-- Devices to create in exclusive IP zone only --> + <device match="dld" ip-type="exclusive" /> <device match="icmp" ip-type="exclusive" /> <device match="icmp6" ip-type="exclusive" /> <device match="ip" ip-type="exclusive" /> @@ -108,6 +109,7 @@ <device match="ipsecesp" ip-type="exclusive" /> <device match="ipstate" ip-type="exclusive" /> <device match="ipsync" ip-type="exclusive" /> + <device match="iptunq" ip-type="exclusive" /> <device match="keysock" ip-type="exclusive" /> <device match="rawip" ip-type="exclusive" /> <device match="rawip6" ip-type="exclusive" /> diff --git a/usr/src/lib/libc/port/sys/zone.c b/usr/src/lib/libc/port/sys/zone.c index 5129e5d576..4a4c70043d 100644 --- a/usr/src/lib/libc/port/sys/zone.c +++ b/usr/src/lib/libc/port/sys/zone.c @@ -20,12 +20,10 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "lint.h" #include <sys/types.h> #include <sys/syscall.h> @@ -220,27 +218,26 @@ zone_version(int *version) return (syscall(SYS_zone, ZONE_VERSION, version)); } - int -zone_add_datalink(zoneid_t zoneid, char *dlname) +zone_add_datalink(zoneid_t zoneid, datalink_id_t linkid) { - return (syscall(SYS_zone, ZONE_ADD_DATALINK, zoneid, dlname)); + return (syscall(SYS_zone, ZONE_ADD_DATALINK, zoneid, linkid)); } int -zone_remove_datalink(zoneid_t zoneid, char *dlname) +zone_remove_datalink(zoneid_t zoneid, datalink_id_t linkid) { - return (syscall(SYS_zone, ZONE_DEL_DATALINK, zoneid, dlname)); + return (syscall(SYS_zone, ZONE_DEL_DATALINK, zoneid, linkid)); } int -zone_check_datalink(zoneid_t *zoneidp, char *dlname) +zone_check_datalink(zoneid_t *zoneidp, datalink_id_t linkid) { - return (syscall(SYS_zone, ZONE_CHECK_DATALINK, zoneidp, dlname)); + return (syscall(SYS_zone, ZONE_CHECK_DATALINK, zoneidp, linkid)); } int -zone_list_datalink(zoneid_t zoneid, int *dlnump, char *buf) +zone_list_datalink(zoneid_t zoneid, int *dlnump, datalink_id_t *linkids) { - return (syscall(SYS_zone, ZONE_LIST_DATALINK, zoneid, dlnump, buf)); + return (syscall(SYS_zone, ZONE_LIST_DATALINK, zoneid, dlnump, linkids)); } diff --git a/usr/src/lib/libdladm/Makefile b/usr/src/lib/libdladm/Makefile index 7765c65ab8..3e5457f227 100644 --- a/usr/src/lib/libdladm/Makefile +++ b/usr/src/lib/libdladm/Makefile @@ -29,7 +29,7 @@ include $(SRC)/lib/Makefile.lib HDRS = libdladm.h libdladm_impl.h libdllink.h libdlaggr.h \ libdlwlan.h libdlwlan_impl.h libdlvnic.h libdlvlan.h \ libdlmgmt.h libdlflow.h libdlflow_impl.h libdlstat.h \ - libdlether.h libdlsim.h libdlbridge.h + libdlether.h libdlsim.h libdlbridge.h libdliptun.h HDRDIR = common @@ -45,7 +45,7 @@ MSGFILES = common/libdladm.c common/linkprop.c common/secobj.c \ common/propfuncs.c common/libdlflow.c \ common/libdlstat.c common/flowattr.c \ common/libdlether.c common/libdlsim.c \ - common/libdlbridge.c + common/libdlbridge.c common/libdliptun.c XGETFLAGS = -a -x libdladm.xcl diff --git a/usr/src/lib/libdladm/Makefile.com b/usr/src/lib/libdladm/Makefile.com index 1ad7a7c961..84d4f28fd4 100644 --- a/usr/src/lib/libdladm/Makefile.com +++ b/usr/src/lib/libdladm/Makefile.com @@ -28,7 +28,7 @@ VERS = .1 OBJECTS = libdladm.o secobj.o linkprop.o libdllink.o libdlaggr.o \ libdlwlan.o libdlvnic.o libdlmgmt.o libdlvlan.o \ flowattr.o flowprop.o propfuncs.o libdlflow.o libdlstat.o \ - usage.o libdlether.o libdlsim.o libdlbridge.o + usage.o libdlether.o libdlsim.o libdlbridge.o libdliptun.o include ../../Makefile.lib diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c index 90d1d7fdaf..9e03468c7d 100644 --- a/usr/src/lib/libdladm/common/libdladm.c +++ b/usr/src/lib/libdladm/common/libdladm.c @@ -52,6 +52,7 @@ static media_type_t media_type_table[] = { { DL_IB, "Infiniband" }, { DL_IPV4, "IPv4Tunnel" }, { DL_IPV6, "IPv6Tunnel" }, + { DL_6TO4, "6to4Tunnel" }, { DL_CSMACD, "CSMA/CD" }, { DL_TPB, "TokenBus" }, { DL_TPR, "TokenRing" }, @@ -351,6 +352,21 @@ dladm_status2str(dladm_status_t status, char *buf) case DLADM_STATUS_OPTMISSING: s = "optional software not installed"; break; + case DLADM_STATUS_IPTUNTYPE: + s = "invalid IP tunnel type"; + break; + case DLADM_STATUS_IPTUNTYPEREQD: + s = "IP tunnel type required"; + break; + case DLADM_STATUS_BADIPTUNLADDR: + s = "invalid local IP tunnel address"; + break; + case DLADM_STATUS_BADIPTUNRADDR: + s = "invalid remote IP tunnel address"; + break; + case DLADM_STATUS_ADDRINUSE: + s = "address already in use"; + break; default: s = "<unknown error>"; break; @@ -399,6 +415,8 @@ dladm_errno2status(int err) return (DLADM_STATUS_FLOW_INCOMPATIBLE); case EALREADY: return (DLADM_STATUS_FLOW_IDENTICAL); + case EADDRINUSE: + return (DLADM_STATUS_ADDRINUSE); default: return (DLADM_STATUS_FAILED); } @@ -573,6 +591,9 @@ dladm_class2str(datalink_class_t class, char *buf) case DATALINK_CLASS_ETHERSTUB: s = "etherstub"; break; + case DATALINK_CLASS_IPTUN: + s = "iptun"; + break; case DATALINK_CLASS_SIMNET: s = "simnet"; break; @@ -747,7 +768,7 @@ dladm_valid_linkname(const char *link) size_t len = strlen(link); const char *cp; - if (len + 1 >= MAXLINKNAMELEN) + if (len >= MAXLINKNAMELEN) return (B_FALSE); /* @@ -758,10 +779,10 @@ dladm_valid_linkname(const char *link) /* * The legal characters in a link name are: - * alphanumeric (a-z, A-Z, 0-9), and the underscore ('_'). + * alphanumeric (a-z, A-Z, 0-9), underscore ('_'), and '.'. */ for (cp = link; *cp != '\0'; cp++) { - if ((isalnum(*cp) == 0) && (*cp != '_')) + if ((isalnum(*cp) == 0) && (*cp != '_') && (*cp != '.')) return (B_FALSE); } diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h index 919c207cd0..0e9a066083 100644 --- a/usr/src/lib/libdladm/common/libdladm.h +++ b/usr/src/lib/libdladm/common/libdladm.h @@ -115,6 +115,11 @@ typedef enum { DLADM_STATUS_VIDINVAL, DLADM_STATUS_NONOTIF, DLADM_STATUS_TRYAGAIN, + DLADM_STATUS_IPTUNTYPE, + DLADM_STATUS_IPTUNTYPEREQD, + DLADM_STATUS_BADIPTUNLADDR, + DLADM_STATUS_BADIPTUNRADDR, + DLADM_STATUS_ADDRINUSE, DLADM_STATUS_BADTIMEVAL, DLADM_STATUS_INVALIDMACADDR, DLADM_STATUS_INVALIDMACADDRNIC, @@ -240,6 +245,8 @@ extern dladm_status_t dladm_usage_summary(int (*)(dladm_usage_t *, void *), int, char *, void *); extern dladm_status_t dladm_usage_dates(int (*)(dladm_usage_t *, void *), int, char *, char *, void *); +extern dladm_status_t dladm_zone_boot(dladm_handle_t, zoneid_t); +extern dladm_status_t dladm_zone_halt(dladm_handle_t, zoneid_t); #ifdef __cplusplus } diff --git a/usr/src/lib/libdladm/common/libdladm_impl.h b/usr/src/lib/libdladm/common/libdladm_impl.h index 774d86b0ac..61e584a051 100644 --- a/usr/src/lib/libdladm/common/libdladm_impl.h +++ b/usr/src/lib/libdladm/common/libdladm_impl.h @@ -26,6 +26,7 @@ #ifndef _LIBDLADM_IMPL_H #define _LIBDLADM_IMPL_H +#include <sys/types.h> #include <sys/mac.h> #include <sys/mac_flow.h> #include <libdladm.h> diff --git a/usr/src/lib/libdladm/common/libdlaggr.c b/usr/src/lib/libdladm/common/libdlaggr.c index 408bf828ab..d715ff013c 100644 --- a/usr/src/lib/libdladm/common/libdlaggr.c +++ b/usr/src/lib/libdladm/common/libdlaggr.c @@ -59,26 +59,7 @@ static uchar_t zero_mac[] = {0, 0, 0, 0, 0, 0}; (((mac) != NULL) && (bcmp(zero_mac, (mac), ETHERADDRL) != 0) && \ (!(mac)[0] & 0x01)) -#define PORT_DELIMITER '.' - -#define WRITE_PORT(portstr, portid, size) { \ - char pstr[LINKID_STR_WIDTH + 2]; \ - (void) snprintf(pstr, LINKID_STR_WIDTH + 2, "%d%c", \ - (portid), PORT_DELIMITER); \ - (void) strlcat((portstr), pstr, (size)); \ -} - -#define READ_PORT(portstr, portid, status) { \ - errno = 0; \ - (status) = DLADM_STATUS_OK; \ - (portid) = (int)strtol((portstr), &(portstr), 10); \ - if (errno != 0 || *(portstr) != PORT_DELIMITER) { \ - (status) = DLADM_STATUS_REPOSITORYINVAL; \ - } else { \ - /* Skip the delimiter. */ \ - (portstr)++; \ - } \ -} +#define PORT_DELIMITER ":" typedef struct dladm_aggr_modify_attr { uint32_t ld_policy; @@ -136,6 +117,35 @@ static dladm_aggr_port_state_t port_states[] = { #define NPORT_STATES \ (sizeof (port_states) / sizeof (dladm_aggr_port_state_t)) +static dladm_status_t +write_port(dladm_handle_t handle, char *portstr, datalink_id_t portid, + size_t portstrsize) +{ + char pname[MAXLINKNAMELEN + 1]; + dladm_status_t status; + + if ((status = dladm_datalink_id2info(handle, portid, NULL, NULL, NULL, + pname, sizeof (pname))) != DLADM_STATUS_OK) + return (status); + (void) strlcat(pname, PORT_DELIMITER, sizeof (pname)); + if (strlcat(portstr, pname, portstrsize) >= portstrsize) + status = DLADM_STATUS_TOOSMALL; + return (status); +} + +static dladm_status_t +read_port(dladm_handle_t handle, char **portstr, datalink_id_t *portid) +{ + dladm_status_t status; + char *pname; + + if ((pname = strtok(*portstr, PORT_DELIMITER)) == NULL) + return (DLADM_STATUS_REPOSITORYINVAL); + *portstr += (strlen(pname) + 1); + status = dladm_name2info(handle, pname, portid, NULL, NULL, NULL); + return (status); +} + static int i_dladm_aggr_ioctl(dladm_handle_t handle, int cmd, void *ptr) { @@ -259,7 +269,7 @@ i_dladm_aggr_info_persist(dladm_handle_t handle, datalink_id_t linkid, { dladm_conf_t conf; uint32_t nports, i; - char *portstr, *next; + char *portstr = NULL, *next; dladm_status_t status; uint64_t u64; int size; @@ -323,36 +333,30 @@ i_dladm_aggr_info_persist(dladm_handle_t handle, datalink_id_t linkid, nports = (uint32_t)u64; attrp->lg_nports = nports; - size = nports * (LINKID_STR_WIDTH + 1) + 1; + size = nports * (MAXLINKNAMELEN + 1) + 1; if ((portstr = calloc(1, size)) == NULL) { status = DLADM_STATUS_NOMEM; goto done; } status = dladm_get_conf_field(handle, conf, FPORTS, portstr, size); - if (status != DLADM_STATUS_OK) { - free(portstr); + if (status != DLADM_STATUS_OK) goto done; - } if ((attrp->lg_ports = malloc(nports * sizeof (dladm_aggr_port_attr_t))) == NULL) { - free(portstr); status = DLADM_STATUS_NOMEM; goto done; } for (next = portstr, i = 0; i < nports; i++) { - READ_PORT(next, attrp->lg_ports[i].lp_linkid, status); - if (status != DLADM_STATUS_OK) { - free(portstr); + if ((status = read_port(handle, &next, + &attrp->lg_ports[i].lp_linkid)) != DLADM_STATUS_OK) free(attrp->lg_ports); - goto done; - } } - free(portstr); done: + free(portstr); dladm_destroy_conf(handle, conf); return (status); } @@ -406,7 +410,7 @@ i_dladm_aggr_add_rmv(dladm_handle_t handle, datalink_id_t linkid, * First, update the persistent configuration if requested. We only * need to update the FPORTS and FNPORTS fields of this aggregation. * Note that FPORTS is a list of port linkids separated by - * PORT_DELIMITER ('.'). + * PORT_DELIMITER (':'). */ if (flags & DLADM_OPT_PERSIST) { status = dladm_read_conf(handle, linkid, &conf); @@ -430,7 +434,7 @@ i_dladm_aggr_add_rmv(dladm_handle_t handle, datalink_id_t linkid, goto destroyconf; } - size = orig_nports * (LINKID_STR_WIDTH + 1) + 1; + size = orig_nports * (MAXLINKNAMELEN + 1) + 1; if ((orig_portstr = calloc(1, size)) == NULL) { status = dladm_errno2status(errno); goto destroyconf; @@ -444,7 +448,7 @@ i_dladm_aggr_add_rmv(dladm_handle_t handle, datalink_id_t linkid, result_nports = (cmd == LAIOC_ADD) ? orig_nports + nports : orig_nports; - size = result_nports * (LINKID_STR_WIDTH + 1) + 1; + size = result_nports * (MAXLINKNAMELEN + 1) + 1; if ((portstr = calloc(1, size)) == NULL) { status = dladm_errno2status(errno); goto destroyconf; @@ -456,8 +460,14 @@ i_dladm_aggr_add_rmv(dladm_handle_t handle, datalink_id_t linkid, */ if (cmd == LAIOC_ADD) { (void) strlcpy(portstr, orig_portstr, size); - for (i = 0; i < nports; i++) - WRITE_PORT(portstr, ports[i].lp_linkid, size); + for (i = 0; i < nports; i++) { + status = write_port(handle, portstr, + ports[i].lp_linkid, size); + if (status != DLADM_STATUS_OK) { + free(portstr); + goto destroyconf; + } + } } else { char *next; datalink_id_t portid; @@ -468,7 +478,7 @@ i_dladm_aggr_add_rmv(dladm_handle_t handle, datalink_id_t linkid, * Read the portids from the old configuration * one by one. */ - READ_PORT(next, portid, status); + status = read_port(handle, &next, &portid); if (status != DLADM_STATUS_OK) { free(portstr); goto destroyconf; @@ -483,7 +493,12 @@ i_dladm_aggr_add_rmv(dladm_handle_t handle, datalink_id_t linkid, break; } if (i == nports) { - WRITE_PORT(portstr, portid, size); + status = write_port(handle, portstr, + portid, size); + if (status != DLADM_STATUS_OK) { + free(portstr); + goto destroyconf; + } } else { remove++; } @@ -724,16 +739,10 @@ i_dladm_aggr_up(dladm_handle_t handle, datalink_id_t linkid, void *arg) if ((status = dladm_up_datalink_id(handle, linkid)) != DLADM_STATUS_OK) { laioc_delete_t ioc; + ioc.ld_linkid = linkid; (void) i_dladm_aggr_ioctl(handle, LAIOC_DELETE, &ioc); - goto done; } - - /* - * Reset the active linkprop of this specific link. - */ - (void) dladm_init_linkprop(handle, linkid, B_FALSE); - done: free(attr.lg_ports); free(ports); @@ -1028,14 +1037,19 @@ dladm_aggr_persist_aggr_conf(dladm_handle_t handle, const char *link, if (status != DLADM_STATUS_OK) goto done; - size = nports * (LINKID_STR_WIDTH + 1) + 1; + size = nports * MAXLINKNAMELEN + 1; if ((portstr = calloc(1, size)) == NULL) { status = DLADM_STATUS_NOMEM; goto done; } - for (i = 0; i < nports; i++) - WRITE_PORT(portstr, ports[i].lp_linkid, size); + for (i = 0; i < nports; i++) { + status = write_port(handle, portstr, ports[i].lp_linkid, size); + if (status != DLADM_STATUS_OK) { + free(portstr); + goto done; + } + } status = dladm_set_conf_field(handle, conf, FPORTS, DLADM_TYPE_STR, portstr); free(portstr); @@ -1404,9 +1418,9 @@ dladm_aggr_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) if (arg.isheld) return (DLADM_STATUS_LINKBUSY); + (void) dladm_remove_conf(handle, linkid); (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_PERSIST); - (void) dladm_remove_conf(handle, linkid); } return (DLADM_STATUS_OK); diff --git a/usr/src/lib/libdladm/common/libdliptun.c b/usr/src/lib/libdladm/common/libdliptun.c new file mode 100644 index 0000000000..f73c0d1ecb --- /dev/null +++ b/usr/src/lib/libdladm/common/libdliptun.c @@ -0,0 +1,625 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <assert.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stropts.h> +#include <string.h> +#include <netdb.h> +#include <sys/conf.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <inet/iptun.h> +#include <sys/dls.h> +#include <libdlpi.h> +#include <libdladm_impl.h> +#include <libdllink.h> +#include <libdliptun.h> + +/* + * IP Tunneling Administration Library. + * This library is used by dladm(1M) and to configure IP tunnel links. + */ + +#define IPTUN_CONF_TYPE "type" +#define IPTUN_CONF_LADDR "laddr" +#define IPTUN_CONF_RADDR "raddr" + +/* + * If IPTUN_CREATE and IPTUN_MODIFY include IPsec policy and IPsec hasn't + * loaded yet, the ioctls may return EAGAIN. We try the ioctl + * IPTUN_IOCTL_ATTEMPT_LIMIT times and wait IPTUN_IOCTL_ATTEMPT_INTERVAL + * microseconds between attempts. + */ +#define IPTUN_IOCTL_ATTEMPT_LIMIT 3 +#define IPTUN_IOCTL_ATTEMPT_INTERVAL 10000 + +dladm_status_t +i_iptun_ioctl(dladm_handle_t handle, int cmd, void *dp) +{ + dladm_status_t status = DLADM_STATUS_OK; + uint_t attempt; + + for (attempt = 0; attempt < IPTUN_IOCTL_ATTEMPT_LIMIT; attempt++) { + if (attempt != 0) + (void) usleep(IPTUN_IOCTL_ATTEMPT_INTERVAL); + status = (ioctl(dladm_dld_fd(handle), cmd, dp) == 0) ? + DLADM_STATUS_OK : dladm_errno2status(errno); + if (status != DLADM_STATUS_TRYAGAIN) + break; + } + return (status); +} + +/* + * Given tunnel paramaters as supplied by a library consumer, fill in kernel + * parameters to be passed down to the iptun control device. + */ +static dladm_status_t +i_iptun_kparams(dladm_handle_t handle, const iptun_params_t *params, + iptun_kparams_t *ik) +{ + dladm_status_t status; + struct addrinfo *ai, hints; + iptun_kparams_t tmpik; + iptun_type_t iptuntype = IPTUN_TYPE_UNKNOWN; + + (void) memset(ik, 0, sizeof (*ik)); + + ik->iptun_kparam_linkid = params->iptun_param_linkid; + + if (params->iptun_param_flags & IPTUN_PARAM_TYPE) { + ik->iptun_kparam_type = iptuntype = params->iptun_param_type; + ik->iptun_kparam_flags |= IPTUN_KPARAM_TYPE; + } + + if (params->iptun_param_flags & (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR)) { + if (iptuntype == IPTUN_TYPE_UNKNOWN) { + /* + * We need to get the type of this existing tunnel in + * order to validate and/or look up the right kind of + * IP address. + */ + tmpik.iptun_kparam_linkid = params->iptun_param_linkid; + status = i_iptun_ioctl(handle, IPTUN_INFO, &tmpik); + if (status != DLADM_STATUS_OK) + return (status); + iptuntype = tmpik.iptun_kparam_type; + } + + (void) memset(&hints, 0, sizeof (hints)); + switch (iptuntype) { + case IPTUN_TYPE_IPV4: + case IPTUN_TYPE_6TO4: + hints.ai_family = AF_INET; + break; + case IPTUN_TYPE_IPV6: + hints.ai_family = AF_INET6; + break; + } + } + + if (params->iptun_param_flags & IPTUN_PARAM_LADDR) { + if (getaddrinfo(params->iptun_param_laddr, NULL, &hints, &ai) != + 0) + return (DLADM_STATUS_BADIPTUNLADDR); + if (ai->ai_next != NULL) { + freeaddrinfo(ai); + return (DLADM_STATUS_BADIPTUNLADDR); + } + (void) memcpy(&ik->iptun_kparam_laddr, ai->ai_addr, + ai->ai_addrlen); + ik->iptun_kparam_flags |= IPTUN_KPARAM_LADDR; + freeaddrinfo(ai); + } + + if (params->iptun_param_flags & IPTUN_PARAM_RADDR) { + if (getaddrinfo(params->iptun_param_raddr, NULL, &hints, &ai) != + 0) + return (DLADM_STATUS_BADIPTUNRADDR); + if (ai->ai_next != NULL) { + freeaddrinfo(ai); + return (DLADM_STATUS_BADIPTUNRADDR); + } + (void) memcpy(&ik->iptun_kparam_raddr, ai->ai_addr, + ai->ai_addrlen); + ik->iptun_kparam_flags |= IPTUN_KPARAM_RADDR; + freeaddrinfo(ai); + } + + if (params->iptun_param_flags & IPTUN_PARAM_SECINFO) { + ik->iptun_kparam_secinfo = params->iptun_param_secinfo; + ik->iptun_kparam_flags |= IPTUN_KPARAM_SECINFO; + } + + return (DLADM_STATUS_OK); +} + +/* + * The inverse of i_iptun_kparams(). Given kernel tunnel paramaters as + * returned from an IPTUN_INFO ioctl, fill in tunnel parameters. + */ +static dladm_status_t +i_iptun_params(const iptun_kparams_t *ik, iptun_params_t *params) +{ + socklen_t salen; + + (void) memset(params, 0, sizeof (*params)); + + params->iptun_param_linkid = ik->iptun_kparam_linkid; + + if (ik->iptun_kparam_flags & IPTUN_KPARAM_TYPE) { + params->iptun_param_type = ik->iptun_kparam_type; + params->iptun_param_flags |= IPTUN_PARAM_TYPE; + } + + if (ik->iptun_kparam_flags & IPTUN_KPARAM_LADDR) { + salen = ik->iptun_kparam_laddr.ss_family == AF_INET ? + sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6); + if (getnameinfo((const struct sockaddr *) + &ik->iptun_kparam_laddr, salen, params->iptun_param_laddr, + sizeof (params->iptun_param_laddr), NULL, 0, + NI_NUMERICHOST) != 0) { + return (DLADM_STATUS_BADIPTUNLADDR); + } + params->iptun_param_flags |= IPTUN_PARAM_LADDR; + } + + if (ik->iptun_kparam_flags & IPTUN_KPARAM_RADDR) { + salen = ik->iptun_kparam_raddr.ss_family == AF_INET ? + sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6); + if (getnameinfo((const struct sockaddr *) + &ik->iptun_kparam_raddr, salen, params->iptun_param_raddr, + sizeof (params->iptun_param_raddr), NULL, 0, + NI_NUMERICHOST) != 0) { + return (DLADM_STATUS_BADIPTUNRADDR); + } + params->iptun_param_flags |= IPTUN_PARAM_RADDR; + } + + if (ik->iptun_kparam_flags & IPTUN_KPARAM_SECINFO) { + params->iptun_param_secinfo = ik->iptun_kparam_secinfo; + params->iptun_param_flags |= IPTUN_PARAM_SECINFO; + } + + if (ik->iptun_kparam_flags & IPTUN_KPARAM_IMPLICIT) + params->iptun_param_flags |= IPTUN_PARAM_IMPLICIT; + + if (ik->iptun_kparam_flags & IPTUN_KPARAM_IPSECPOL) + params->iptun_param_flags |= IPTUN_PARAM_IPSECPOL; + + return (DLADM_STATUS_OK); +} + +dladm_status_t +i_iptun_get_sysparams(dladm_handle_t handle, iptun_params_t *params) +{ + dladm_status_t status = DLADM_STATUS_OK; + iptun_kparams_t ik; + + ik.iptun_kparam_linkid = params->iptun_param_linkid; + status = i_iptun_ioctl(handle, IPTUN_INFO, &ik); + if (status == DLADM_STATUS_OK) + status = i_iptun_params(&ik, params); + return (status); +} + +/* + * Read tunnel parameters from persistent storage. Note that the tunnel type + * is the only thing which must always be in the configuratioh. All other + * parameters (currently the source and destination addresses) may or may not + * have been configured, and therefore may not have been set. + */ +static dladm_status_t +i_iptun_get_dbparams(dladm_handle_t handle, iptun_params_t *params) +{ + dladm_status_t status; + dladm_conf_t conf; + datalink_class_t class; + uint64_t temp; + + /* First, make sure that this is an IP tunnel. */ + if ((status = dladm_datalink_id2info(handle, params->iptun_param_linkid, + NULL, &class, NULL, NULL, 0)) != DLADM_STATUS_OK) + return (status); + if (class != DATALINK_CLASS_IPTUN) + return (DLADM_STATUS_LINKINVAL); + + status = dladm_read_conf(handle, params->iptun_param_linkid, &conf); + if (status != DLADM_STATUS_OK) + return (status); + + params->iptun_param_flags = 0; + + if ((status = dladm_get_conf_field(handle, conf, IPTUN_CONF_TYPE, &temp, + sizeof (temp))) != DLADM_STATUS_OK) + goto done; + params->iptun_param_type = (iptun_type_t)temp; + params->iptun_param_flags |= IPTUN_PARAM_TYPE; + + if (dladm_get_conf_field(handle, conf, IPTUN_CONF_LADDR, + params->iptun_param_laddr, sizeof (params->iptun_param_laddr)) == + DLADM_STATUS_OK) + params->iptun_param_flags |= IPTUN_PARAM_LADDR; + + if (dladm_get_conf_field(handle, conf, IPTUN_CONF_RADDR, + params->iptun_param_raddr, sizeof (params->iptun_param_raddr)) == + DLADM_STATUS_OK) + params->iptun_param_flags |= IPTUN_PARAM_RADDR; + +done: + dladm_destroy_conf(handle, conf); + return (status); +} + +static dladm_status_t +i_iptun_create_sys(dladm_handle_t handle, iptun_params_t *params) +{ + iptun_kparams_t ik; + dladm_status_t status = DLADM_STATUS_OK; + + /* The tunnel type is required for creation. */ + if (!(params->iptun_param_flags & IPTUN_PARAM_TYPE)) + return (DLADM_STATUS_IPTUNTYPEREQD); + + if ((status = i_iptun_kparams(handle, params, &ik)) == DLADM_STATUS_OK) + status = i_iptun_ioctl(handle, IPTUN_CREATE, &ik); + return (status); +} + +static dladm_status_t +i_iptun_create_db(dladm_handle_t handle, const char *name, + iptun_params_t *params, uint32_t media) +{ + dladm_conf_t conf; + dladm_status_t status; + uint64_t storage; + + status = dladm_create_conf(handle, name, params->iptun_param_linkid, + DATALINK_CLASS_IPTUN, media, &conf); + if (status != DLADM_STATUS_OK) + return (status); + + assert(params->iptun_param_flags & IPTUN_PARAM_TYPE); + storage = params->iptun_param_type; + status = dladm_set_conf_field(handle, conf, IPTUN_CONF_TYPE, + DLADM_TYPE_UINT64, &storage); + if (status != DLADM_STATUS_OK) + goto done; + + if (params->iptun_param_flags & IPTUN_PARAM_LADDR) { + status = dladm_set_conf_field(handle, conf, IPTUN_CONF_LADDR, + DLADM_TYPE_STR, params->iptun_param_laddr); + if (status != DLADM_STATUS_OK) + goto done; + } + + if (params->iptun_param_flags & IPTUN_PARAM_RADDR) { + status = dladm_set_conf_field(handle, conf, IPTUN_CONF_RADDR, + DLADM_TYPE_STR, params->iptun_param_raddr); + if (status != DLADM_STATUS_OK) + goto done; + } + + status = dladm_write_conf(handle, conf); + +done: + dladm_destroy_conf(handle, conf); + return (status); +} + +static dladm_status_t +i_iptun_delete_sys(dladm_handle_t handle, datalink_id_t linkid) +{ + dladm_status_t status; + + status = i_iptun_ioctl(handle, IPTUN_DELETE, &linkid); + if (status != DLADM_STATUS_OK) + return (status); + (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_ACTIVE); + return (DLADM_STATUS_OK); +} + +static dladm_status_t +i_iptun_modify_sys(dladm_handle_t handle, const iptun_params_t *params) +{ + iptun_kparams_t ik; + dladm_status_t status; + + if ((status = i_iptun_kparams(handle, params, &ik)) == DLADM_STATUS_OK) + status = i_iptun_ioctl(handle, IPTUN_MODIFY, &ik); + return (status); +} + +static dladm_status_t +i_iptun_modify_db(dladm_handle_t handle, const iptun_params_t *params) +{ + dladm_conf_t conf; + dladm_status_t status; + + assert(params->iptun_param_flags & + (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR)); + + /* + * The only parameters that can be modified persistently are the local + * and remote addresses. + */ + if (params->iptun_param_flags & ~(IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR)) + return (DLADM_STATUS_BADARG); + + status = dladm_read_conf(handle, params->iptun_param_linkid, &conf); + if (status != DLADM_STATUS_OK) + return (status); + + if (params->iptun_param_flags & IPTUN_PARAM_LADDR) { + status = dladm_set_conf_field(handle, conf, IPTUN_CONF_LADDR, + DLADM_TYPE_STR, (void *)params->iptun_param_laddr); + if (status != DLADM_STATUS_OK) + goto done; + } + + if (params->iptun_param_flags & IPTUN_PARAM_RADDR) { + status = dladm_set_conf_field(handle, conf, IPTUN_CONF_RADDR, + DLADM_TYPE_STR, (void *)params->iptun_param_raddr); + if (status != DLADM_STATUS_OK) + goto done; + } + + status = dladm_write_conf(handle, conf); + +done: + dladm_destroy_conf(handle, conf); + return (status); +} + +dladm_status_t +dladm_iptun_create(dladm_handle_t handle, const char *name, + iptun_params_t *params, uint32_t flags) +{ + dladm_status_t status; + uint32_t linkmgmt_flags = flags; + uint32_t media; + + if (!(params->iptun_param_flags & IPTUN_PARAM_TYPE)) + return (DLADM_STATUS_IPTUNTYPEREQD); + + switch (params->iptun_param_type) { + case IPTUN_TYPE_IPV4: + media = DL_IPV4; + break; + case IPTUN_TYPE_IPV6: + media = DL_IPV6; + break; + case IPTUN_TYPE_6TO4: + media = DL_6TO4; + break; + default: + return (DLADM_STATUS_IPTUNTYPE); + } + + status = dladm_create_datalink_id(handle, name, DATALINK_CLASS_IPTUN, + media, linkmgmt_flags, ¶ms->iptun_param_linkid); + if (status != DLADM_STATUS_OK) + return (status); + + if (flags & DLADM_OPT_PERSIST) { + status = i_iptun_create_db(handle, name, params, media); + if (status != DLADM_STATUS_OK) + goto done; + } + + if (flags & DLADM_OPT_ACTIVE) { + status = i_iptun_create_sys(handle, params); + if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST)) { + (void) dladm_remove_conf(handle, + params->iptun_param_linkid); + } + } + +done: + if (status != DLADM_STATUS_OK) { + (void) dladm_destroy_datalink_id(handle, + params->iptun_param_linkid, flags); + } + return (status); +} + +dladm_status_t +dladm_iptun_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) +{ + dladm_status_t status; + datalink_class_t class; + + /* First, make sure that this is an IP tunnel. */ + if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL, + NULL, 0)) != DLADM_STATUS_OK) + return (status); + if (class != DATALINK_CLASS_IPTUN) + return (DLADM_STATUS_LINKINVAL); + + if (flags & DLADM_OPT_ACTIVE) { + /* + * Note that if i_iptun_delete_sys() fails with + * DLADM_STATUS_NOTFOUND and the caller also wishes to delete + * the persistent configuration, we still fall through to the + * DLADM_OPT_PERSIST case in case the tunnel only exists + * persistently. + */ + status = i_iptun_delete_sys(handle, linkid); + if (status != DLADM_STATUS_OK && + (status != DLADM_STATUS_NOTFOUND || + !(flags & DLADM_OPT_PERSIST))) + return (status); + } + + if (flags & DLADM_OPT_PERSIST) { + (void) dladm_remove_conf(handle, linkid); + (void) dladm_destroy_datalink_id(handle, linkid, + DLADM_OPT_PERSIST); + } + return (DLADM_STATUS_OK); +} + +dladm_status_t +dladm_iptun_modify(dladm_handle_t handle, const iptun_params_t *params, + uint32_t flags) +{ + dladm_status_t status = DLADM_STATUS_OK; + iptun_params_t old_params; + + /* + * We can only modify the tunnel source, tunnel destination, or IPsec + * policy. + */ + if (!(params->iptun_param_flags & + (IPTUN_PARAM_LADDR|IPTUN_PARAM_RADDR|IPTUN_PARAM_SECINFO))) + return (DLADM_STATUS_BADARG); + + if (flags & DLADM_OPT_PERSIST) { + /* + * Before we change the database, save the old configuration + * so that we can revert back if an error occurs. + */ + old_params.iptun_param_linkid = params->iptun_param_linkid; + status = i_iptun_get_dbparams(handle, &old_params); + if (status != DLADM_STATUS_OK) + return (status); + /* we'll only need to revert the parameters being modified */ + old_params.iptun_param_flags = params->iptun_param_flags; + + status = i_iptun_modify_db(handle, params); + if (status != DLADM_STATUS_OK) + return (status); + } + + if (flags & DLADM_OPT_ACTIVE) { + status = i_iptun_modify_sys(handle, params); + if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_PERSIST)) { + (void) i_iptun_modify_db(handle, &old_params); + } + } + + return (status); +} + +dladm_status_t +dladm_iptun_getparams(dladm_handle_t handle, iptun_params_t *params, + uint32_t flags) +{ + if (flags == DLADM_OPT_ACTIVE) + return (i_iptun_get_sysparams(handle, params)); + else if (flags == DLADM_OPT_PERSIST) + return (i_iptun_get_dbparams(handle, params)); + else + return (DLADM_STATUS_BADARG); +} + +static int +i_iptun_up(dladm_handle_t handle, datalink_id_t linkid, void *arg) +{ + dladm_status_t *statusp = arg; + dladm_status_t status; + iptun_params_t params; + boolean_t id_up = B_FALSE; + + status = dladm_up_datalink_id(handle, linkid); + if (status != DLADM_STATUS_OK) + goto done; + id_up = B_TRUE; + + (void) memset(¶ms, 0, sizeof (params)); + + params.iptun_param_linkid = linkid; + if ((status = i_iptun_get_dbparams(handle, ¶ms)) == DLADM_STATUS_OK) + status = i_iptun_create_sys(handle, ¶ms); +done: + if (statusp != NULL) + *statusp = status; + if (status != DLADM_STATUS_OK && id_up) { + (void) dladm_destroy_datalink_id(handle, linkid, + DLADM_OPT_ACTIVE); + } + return (DLADM_WALK_CONTINUE); +} + +static int +i_iptun_down(dladm_handle_t handle, datalink_id_t linkid, void *arg) +{ + dladm_status_t *statusp = arg; + dladm_status_t status; + + status = i_iptun_delete_sys(handle, linkid); + if (statusp != NULL) + *statusp = status; + return (DLADM_WALK_CONTINUE); +} + +/* ARGSUSED */ +dladm_status_t +dladm_iptun_up(dladm_handle_t handle, datalink_id_t linkid) +{ + dladm_status_t status = DLADM_STATUS_OK; + + if (linkid == DATALINK_ALL_LINKID) { + (void) dladm_walk_datalink_id(i_iptun_up, handle, NULL, + DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE, + DLADM_OPT_PERSIST); + } else { + (void) i_iptun_up(handle, linkid, &status); + } + return (status); +} + +dladm_status_t +dladm_iptun_down(dladm_handle_t handle, datalink_id_t linkid) +{ + dladm_status_t status = DLADM_STATUS_OK; + + if (linkid == DATALINK_ALL_LINKID) { + (void) dladm_walk_datalink_id(i_iptun_down, handle, NULL, + DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE, + DLADM_OPT_ACTIVE); + } else { + (void) i_iptun_down(handle, linkid, &status); + } + return (status); +} + +dladm_status_t +dladm_iptun_set6to4relay(dladm_handle_t handle, struct in_addr *relay) +{ + return (i_iptun_ioctl(handle, IPTUN_SET_6TO4RELAY, relay)); +} + +dladm_status_t +dladm_iptun_get6to4relay(dladm_handle_t handle, struct in_addr *relay) +{ + return (i_iptun_ioctl(handle, IPTUN_GET_6TO4RELAY, relay)); +} diff --git a/usr/src/lib/libdladm/common/libdliptun.h b/usr/src/lib/libdladm/common/libdliptun.h new file mode 100644 index 0000000000..287682f5a3 --- /dev/null +++ b/usr/src/lib/libdladm/common/libdliptun.h @@ -0,0 +1,75 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBDLIPTUN_H +#define _LIBDLIPTUN_H + +#include <netdb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <inet/iptun.h> +#include <libdladm.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct iptun_params { + datalink_id_t iptun_param_linkid; + uint_t iptun_param_flags; + iptun_type_t iptun_param_type; + char iptun_param_laddr[NI_MAXHOST]; /* local address */ + char iptun_param_raddr[NI_MAXHOST]; /* remote address */ + ipsec_req_t iptun_param_secinfo; +} iptun_params_t; + +/* iptun_param_flags */ +#define IPTUN_PARAM_TYPE 0x00000001 /* itp_type is set */ +#define IPTUN_PARAM_LADDR 0x00000002 /* itp_laddr is set */ +#define IPTUN_PARAM_RADDR 0x00000004 /* itp_raddr is set */ +#define IPTUN_PARAM_SECINFO 0x00000008 /* itp_secinfo is set */ +#define IPTUN_PARAM_IMPLICIT 0x00000010 /* implicitly created IP tunnel */ +#define IPTUN_PARAM_IPSECPOL 0x00000020 /* IPsec policy exists */ + +extern dladm_status_t dladm_iptun_create(dladm_handle_t, const char *, + iptun_params_t *, uint_t); +extern dladm_status_t dladm_iptun_delete(dladm_handle_t, datalink_id_t, + uint_t); +extern dladm_status_t dladm_iptun_modify(dladm_handle_t, + const iptun_params_t *, uint_t); +extern dladm_status_t dladm_iptun_getparams(dladm_handle_t, iptun_params_t *, + uint_t); +extern dladm_status_t dladm_iptun_up(dladm_handle_t, datalink_id_t); +extern dladm_status_t dladm_iptun_down(dladm_handle_t, datalink_id_t); +extern dladm_status_t dladm_iptun_set6to4relay(dladm_handle_t, + struct in_addr *); +extern dladm_status_t dladm_iptun_get6to4relay(dladm_handle_t, + struct in_addr *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBDLIPTUN_H */ diff --git a/usr/src/lib/libdladm/common/libdllink.c b/usr/src/lib/libdladm/common/libdllink.c index c73e7e0b92..4c2ca93c8c 100644 --- a/usr/src/lib/libdladm/common/libdllink.c +++ b/usr/src/lib/libdladm/common/libdllink.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -379,28 +379,6 @@ dladm_linkduplex2str(link_duplex_t duplex, char *buf) } /* - * Set zoneid of a given link. Note that this function takes a link name - * argument instead of a linkid, because a data-link (and its linkid) could - * be created implicitly as the result of this function. - */ -dladm_status_t -dladm_setzid(dladm_handle_t handle, const char *dlname, char *zone_name) -{ - datalink_id_t linkid; - dladm_status_t status = DLADM_STATUS_OK; - - /* If the link does not exist, it is a ppa-hacked vlan. */ - status = dladm_name2info(handle, dlname, &linkid, NULL, NULL, NULL); - if (status != DLADM_STATUS_OK) - return (status); - - status = dladm_set_linkprop(handle, linkid, "zone", &zone_name, 1, - DLADM_OPT_ACTIVE); - - return (status); -} - -/* * Case 1: rename an existing link1 to a link2 that does not exist. * Result: <linkid1, link2> */ @@ -409,7 +387,6 @@ i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, const char *link1, const char *link2, uint32_t flags) { dld_ioc_rename_t dir; - dladm_conf_t conf; dladm_status_t status = DLADM_STATUS_OK; /* @@ -428,24 +405,9 @@ i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, } status = dladm_remap_datalink_id(handle, linkid1, link2); - if (status != DLADM_STATUS_OK) - goto done; - - /* - * Flush the current mapping to persistent configuration. - */ - if ((flags & DLADM_OPT_PERSIST) && - (((status = dladm_read_conf(handle, linkid1, &conf)) != - DLADM_STATUS_OK) || - ((status = dladm_write_conf(handle, conf)) != DLADM_STATUS_OK))) { - (void) dladm_remap_datalink_id(handle, linkid1, link1); - } -done: - if (flags & DLADM_OPT_ACTIVE) { - if (status != DLADM_STATUS_OK) { - (void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN); - (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir); - } + if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) { + (void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN); + (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir); } return (status); } @@ -586,9 +548,9 @@ i_dladm_rename_link_c2(dladm_handle_t handle, datalink_id_t linkid1, /* * Delete link1 and mark link2 up. */ + (void) dladm_remove_conf(handle, linkid1); (void) dladm_destroy_datalink_id(handle, linkid1, DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST); - (void) dladm_remove_conf(handle, linkid1); (void) dladm_up_datalink_id(handle, linkid2); /* @@ -801,9 +763,8 @@ i_dladm_phys_delete(dladm_handle_t handle, datalink_id_t linkid, void *arg) DLADM_OPT_PERSIST); } - (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_PERSIST); (void) dladm_remove_conf(handle, linkid); - + (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_PERSIST); done: del_phys_arg->rval = status; return (DLADM_WALK_CONTINUE); diff --git a/usr/src/lib/libdladm/common/libdllink.h b/usr/src/lib/libdladm/common/libdllink.h index 6e3b0c97a3..d47059e1d1 100644 --- a/usr/src/lib/libdladm/common/libdllink.h +++ b/usr/src/lib/libdladm/common/libdllink.h @@ -119,7 +119,6 @@ extern dladm_status_t dladm_walk(dladm_walkcb_t *, dladm_handle_t, void *, extern dladm_status_t dladm_mac_walk(dladm_walkcb_t *, void *); extern dladm_status_t dladm_info(dladm_handle_t, datalink_id_t, dladm_attr_t *); -extern dladm_status_t dladm_setzid(dladm_handle_t, const char *, char *); extern dladm_status_t dladm_rename_link(dladm_handle_t, const char *, const char *); diff --git a/usr/src/lib/libdladm/common/libdlmgmt.c b/usr/src/lib/libdladm/common/libdlmgmt.c index c642567fd5..db107ed094 100644 --- a/usr/src/lib/libdladm/common/libdlmgmt.c +++ b/usr/src/lib/libdladm/common/libdlmgmt.c @@ -31,6 +31,7 @@ #include <unistd.h> #include <string.h> #include <strings.h> +#include <zone.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/aggr.h> @@ -607,3 +608,27 @@ dladm_destroy_conf(dladm_handle_t handle, dladm_conf_t conf) (void) dladm_door_call(handle, &destroyconf, sizeof (destroyconf), &retval, sizeof (retval)); } + +dladm_status_t +dladm_zone_boot(dladm_handle_t handle, zoneid_t zoneid) +{ + dlmgmt_door_zoneboot_t zoneboot; + dlmgmt_zoneboot_retval_t retval; + + zoneboot.ld_cmd = DLMGMT_CMD_ZONEBOOT; + zoneboot.ld_zoneid = zoneid; + return (dladm_door_call(handle, &zoneboot, sizeof (zoneboot), &retval, + sizeof (retval))); +} + +dladm_status_t +dladm_zone_halt(dladm_handle_t handle, zoneid_t zoneid) +{ + dlmgmt_door_zonehalt_t zonehalt; + dlmgmt_zonehalt_retval_t retval; + + zonehalt.ld_cmd = DLMGMT_CMD_ZONEHALT; + zonehalt.ld_zoneid = zoneid; + return (dladm_door_call(handle, &zonehalt, sizeof (zonehalt), &retval, + sizeof (retval))); +} diff --git a/usr/src/lib/libdladm/common/libdlmgmt.h b/usr/src/lib/libdladm/common/libdlmgmt.h index 35156c2f97..c170629647 100644 --- a/usr/src/lib/libdladm/common/libdlmgmt.h +++ b/usr/src/lib/libdladm/common/libdlmgmt.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -58,6 +58,8 @@ extern "C" { #define DLMGMT_CMD_DESTROYCONF (DLMGMT_CMD_BASE + 10) #define DLMGMT_CMD_GETATTR (DLMGMT_CMD_BASE + 11) #define DLMGMT_CMD_LINKPROP_GETNEXT (DLMGMT_CMD_BASE + 12) +#define DLMGMT_CMD_ZONEBOOT (DLMGMT_CMD_BASE + 13) +#define DLMGMT_CMD_ZONEHALT (DLMGMT_CMD_BASE + 14) typedef struct dlmgmt_door_createid_s { int ld_cmd; @@ -153,6 +155,11 @@ typedef struct dlmgmt_linkprop_getnext_retval_s { char lr_attrval[MAXLINKATTRVALLEN]; } dlmgmt_linkprop_getnext_retval_t; +typedef struct dlmgmt_door_zone_s { + int ld_cmd; + zoneid_t ld_zoneid; +} dlmgmt_door_zoneboot_t, dlmgmt_door_zonehalt_t; + typedef struct dlmgmt_retval_s dlmgmt_remapid_retval_t, dlmgmt_upid_retval_t, dlmgmt_destroyid_retval_t, @@ -160,7 +167,9 @@ typedef struct dlmgmt_retval_s dlmgmt_remapid_retval_t, dlmgmt_unsetattr_retval_t, dlmgmt_writeconf_retval_t, dlmgmt_removeconf_retval_t, - dlmgmt_destroyconf_retval_t; + dlmgmt_destroyconf_retval_t, + dlmgmt_zoneboot_retval_t, + dlmgmt_zonehalt_retval_t; typedef struct dlmgmt_linkid_retval_s dlmgmt_createid_retval_t; diff --git a/usr/src/lib/libdladm/common/libdlsim.c b/usr/src/lib/libdladm/common/libdlsim.c index 5368db7d0a..a588073bfb 100644 --- a/usr/src/lib/libdladm/common/libdlsim.c +++ b/usr/src/lib/libdladm/common/libdlsim.c @@ -138,6 +138,7 @@ i_dladm_get_simnet_info_persist(dladm_handle_t handle, dladm_conf_t conf; dladm_status_t status; char macstr[ETHERADDRL * 3]; + char simnetpeer[MAXLINKNAMELEN]; uint64_t u64; boolean_t mac_fixed; @@ -164,11 +165,13 @@ i_dladm_get_simnet_info_persist(dladm_handle_t handle, (void) dladm_aggr_str2macaddr(macstr, &mac_fixed, attrp->sna_mac_addr); /* Peer field is optional and only set when peer is attached */ - if (dladm_get_conf_field(handle, conf, FSIMNETPEER, &u64, - sizeof (u64)) == DLADM_STATUS_OK) - attrp->sna_peer_link_id = (datalink_id_t)u64; - else + if (dladm_get_conf_field(handle, conf, FSIMNETPEER, simnetpeer, + sizeof (simnetpeer)) == DLADM_STATUS_OK) { + status = dladm_name2info(handle, simnetpeer, + &attrp->sna_peer_link_id, NULL, NULL, NULL); + } else { attrp->sna_peer_link_id = DATALINK_INVALID_LINKID; + } done: dladm_destroy_conf(handle, conf); return (status); @@ -223,7 +226,7 @@ i_dladm_simnet_update_conf(dladm_handle_t handle, datalink_id_t simnet_id, { dladm_status_t status; dladm_conf_t conf; - uint64_t u64; + char simnetpeer[MAXLINKNAMELEN]; status = dladm_read_conf(handle, simnet_id, &conf); if (status != DLADM_STATUS_OK) @@ -232,12 +235,12 @@ i_dladm_simnet_update_conf(dladm_handle_t handle, datalink_id_t simnet_id, /* First clear previous peer if any in configuration */ (void) dladm_unset_conf_field(handle, conf, FSIMNETPEER); if (peer_simnet_id != DATALINK_INVALID_LINKID) { - u64 = peer_simnet_id; if ((status = dladm_datalink_id2info(handle, - peer_simnet_id, NULL, NULL, NULL, NULL, - 0)) == DLADM_STATUS_OK) + peer_simnet_id, NULL, NULL, NULL, simnetpeer, + sizeof (simnetpeer))) == DLADM_STATUS_OK) { status = dladm_set_conf_field(handle, conf, - FSIMNETPEER, DLADM_TYPE_UINT64, &u64); + FSIMNETPEER, DLADM_TYPE_STR, simnetpeer); + } if (status != DLADM_STATUS_OK) goto fail; } @@ -357,9 +360,9 @@ dladm_simnet_delete(dladm_handle_t handle, datalink_id_t simnet_id, } if (flags & DLADM_OPT_PERSIST) { + (void) dladm_remove_conf(handle, simnet_id); (void) dladm_destroy_datalink_id(handle, simnet_id, DLADM_OPT_PERSIST); - (void) dladm_remove_conf(handle, simnet_id); /* Update any attached peer configuration */ if (prevattr.sna_peer_link_id != DATALINK_INVALID_LINKID) diff --git a/usr/src/lib/libdladm/common/libdlvnic.c b/usr/src/lib/libdladm/common/libdlvnic.c index 2984c42dcc..74a4339c45 100644 --- a/usr/src/lib/libdladm/common/libdlvnic.c +++ b/usr/src/lib/libdladm/common/libdlvnic.c @@ -187,6 +187,7 @@ i_dladm_vnic_info_persist(dladm_handle_t handle, datalink_id_t linkid, dladm_conf_t conf; dladm_status_t status; char macstr[ETHERADDRL * 3]; + char linkover[MAXLINKNAMELEN]; uint64_t u64; datalink_class_t class; @@ -195,10 +196,19 @@ i_dladm_vnic_info_persist(dladm_handle_t handle, datalink_id_t linkid, DLADM_STATUS_OK) return (status); - status = dladm_get_conf_field(handle, conf, FLINKOVER, &u64, - sizeof (u64)); - attrp->va_link_id = ((status == DLADM_STATUS_OK) ? - (datalink_id_t)u64 : DATALINK_INVALID_LINKID); + status = dladm_get_conf_field(handle, conf, FLINKOVER, linkover, + sizeof (linkover)); + if (status != DLADM_STATUS_OK) { + /* + * This isn't an error, etherstubs don't have a FLINKOVER + * property. + */ + attrp->va_link_id = DATALINK_INVALID_LINKID; + } else { + if ((status = dladm_name2info(handle, linkover, + &attrp->va_link_id, NULL, NULL, NULL)) != DLADM_STATUS_OK) + goto done; + } status = dladm_get_conf_field(handle, conf, FHWRINGS, &attrp->va_hwrings, sizeof (boolean_t)); @@ -509,7 +519,6 @@ dladm_vnic_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) { dladm_status_t status; datalink_class_t class; - dladm_vnic_attr_t attr; if (flags == 0) return (DLADM_STATUS_BADARG); @@ -528,10 +537,6 @@ dladm_vnic_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) } if ((flags & DLADM_OPT_ACTIVE) != 0) { - status = dladm_vnic_info(handle, linkid, &attr, - DLADM_OPT_ACTIVE); - if (status != DLADM_STATUS_OK) - return (status); status = i_dladm_vnic_delete_sys(handle, linkid); if (status == DLADM_STATUS_OK) { (void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0, @@ -544,9 +549,9 @@ dladm_vnic_delete(dladm_handle_t handle, datalink_id_t linkid, uint32_t flags) } } if ((flags & DLADM_OPT_PERSIST) != 0) { + (void) dladm_remove_conf(handle, linkid); (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_PERSIST); - (void) dladm_remove_conf(handle, linkid); } return (dladm_bridge_refresh(handle, linkid)); } @@ -589,6 +594,7 @@ dladm_vnic_persist_conf(dladm_handle_t handle, const char *name, dladm_conf_t conf = DLADM_INVALID_CONF; dladm_status_t status; char macstr[ETHERADDRL * 3]; + char linkover[MAXLINKNAMELEN]; uint64_t u64; if ((status = dladm_create_conf(handle, name, attrp->va_vnic_id, @@ -596,9 +602,12 @@ dladm_vnic_persist_conf(dladm_handle_t handle, const char *name, return (status); if (attrp->va_link_id != DATALINK_INVALID_LINKID) { - u64 = attrp->va_link_id; + status = dladm_datalink_id2info(handle, attrp->va_link_id, NULL, + NULL, NULL, linkover, sizeof (linkover)); + if (status != DLADM_STATUS_OK) + goto done; status = dladm_set_conf_field(handle, conf, FLINKOVER, - DLADM_TYPE_UINT64, &u64); + DLADM_TYPE_STR, linkover); if (status != DLADM_STATUS_OK) goto done; } diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c index b0c0c32f45..d77707be99 100644 --- a/usr/src/lib/libdladm/common/linkprop.c +++ b/usr/src/lib/libdladm/common/linkprop.c @@ -54,6 +54,7 @@ #include <sys/mac_flow.h> #include <inttypes.h> #include <sys/ethernet.h> +#include <inet/iptun.h> #include <net/wpa.h> #include <sys/sysmacros.h> #include <sys/vlan.h> @@ -146,6 +147,7 @@ static pd_setf_t do_set_zone, do_set_rate_prop, set_stp_prop, set_bridge_forward, set_bridge_pvid; static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate, + do_check_hoplimit, do_check_encaplim, i_dladm_uint32_check, do_check_maxbw, do_check_cpus, do_check_priority, check_stp_prop, check_bridge_pvid; @@ -329,6 +331,10 @@ static link_attr_t link_attr[] = { { MAC_PROP_TAGMODE, sizeof (link_tagmode_t), "tagmode"}, + { MAC_PROP_IPTUN_HOPLIMIT, sizeof (uint32_t), "hoplimit"}, + + { MAC_PROP_IPTUN_ENCAPLIMIT, sizeof (uint32_t), "encaplimit"}, + { MAC_PROP_PVID, sizeof (uint16_t), "default_tag"}, { MAC_PROP_LLIMIT, sizeof (uint32_t), "learn_limit"}, @@ -553,6 +559,14 @@ static prop_desc_t prop_table[] = { DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC, DL_ETHER }, + { "hoplimit", { "", 0 }, NULL, 0, + i_dladm_set_public_prop, i_dladm_range_get, i_dladm_uint32_get, + do_check_hoplimit, 0, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE}, + + { "encaplimit", { "", 0 }, NULL, 0, + i_dladm_set_public_prop, i_dladm_range_get, i_dladm_uint32_get, + do_check_encaplim, 0, DATALINK_CLASS_IPTUN, DL_IPV6}, + { "forward", { "1", 1 }, link_01_vals, VALCNT(link_01_vals), set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM, @@ -1360,7 +1374,6 @@ do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, { dladm_status_t status = DLADM_STATUS_OK; zoneid_t zid_old, zid_new; - char link[MAXLINKNAMELEN]; char *cp; dld_ioc_macprop_t *dip; dld_ioc_zid_t *dzp; @@ -1380,75 +1393,25 @@ do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, free(dip); zid_new = dzp->diz_zid; - (void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN); - - /* Do nothing if setting to current value */ if (zid_new == zid_old) - return (status); + return (DLADM_STATUS_OK); - if (zid_new != GLOBAL_ZONEID) { - /* - * If the new zoneid is the global zone, we could destroy - * the link (in the case of an implicitly-created VLAN) as a - * result of setting the zoneid. In that case, we defer the - * operation to the end of this function to avoid recreating - * the VLAN and getting a different linkid during the rollback - * if other operation fails. - * - * Otherwise, this operation will hold a reference to the - * link and prevent a link renaming, so we need to do it - * before other operations. - */ - status = i_dladm_set_public_prop(handle, pdp, linkid, vdp, - val_cnt, flags, media); - if (status != DLADM_STATUS_OK) - return (status); - } + if ((status = i_dladm_set_public_prop(handle, pdp, linkid, vdp, val_cnt, + flags, media)) != DLADM_STATUS_OK) + return (status); + /* + * It is okay to fail to update the /dev entry (some vanity-named + * links do not have a /dev entry). + */ if (zid_old != GLOBAL_ZONEID) { - if (zone_remove_datalink(zid_old, link) != 0 && - errno != ENXIO) { - status = dladm_errno2status(errno); - goto rollback1; - } - - /* - * It is okay to fail to update the /dev entry (some - * vanity-named links do not have a /dev entry). - */ (void) i_dladm_update_deventry(handle, zid_old, linkid, B_FALSE); } - - if (zid_new != GLOBAL_ZONEID) { - if (zone_add_datalink(zid_new, link) != 0) { - status = dladm_errno2status(errno); - goto rollback2; - } - + if (zid_new != GLOBAL_ZONEID) (void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE); - } else { - status = i_dladm_set_public_prop(handle, pdp, linkid, vdp, - val_cnt, flags, media); - if (status != DLADM_STATUS_OK) - goto rollback2; - } return (DLADM_STATUS_OK); - -rollback2: - if (zid_old != GLOBAL_ZONEID) - (void) i_dladm_update_deventry(handle, zid_old, linkid, B_TRUE); - if (zid_old != GLOBAL_ZONEID) - (void) zone_add_datalink(zid_old, link); -rollback1: - if (zid_new != GLOBAL_ZONEID) { - dzp->diz_zid = zid_old; - (void) i_dladm_set_public_prop(handle, pdp, linkid, vdp, - val_cnt, flags, media); - } - - return (status); } /* ARGSUSED */ @@ -1457,7 +1420,6 @@ do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) { char *zone_name; - char linkname[MAXLINKNAMELEN]; zoneid_t zoneid; dladm_status_t status = DLADM_STATUS_OK; dld_ioc_zid_t *dzp; @@ -1469,17 +1431,7 @@ do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, if (dzp == NULL) return (DLADM_STATUS_NOMEM); - if ((status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, - linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) { - goto done; - } - zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME; - if (strlen(linkname) > MAXLINKNAMELEN) { - status = DLADM_STATUS_BADVAL; - goto done; - } - if ((zoneid = getzoneidbyname(zone_name)) == -1) { status = DLADM_STATUS_BADVAL; goto done; @@ -1503,7 +1455,7 @@ do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, (void) memset(dzp, 0, sizeof (dld_ioc_zid_t)); dzp->diz_zid = zoneid; - (void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN); + dzp->diz_linkid = linkid; vdp->vd_val = (uintptr_t)dzp; return (DLADM_STATUS_OK); @@ -2349,7 +2301,7 @@ do_set_radio(dladm_handle_t handle, datalink_id_t linkid, /* ARGSUSED */ static dladm_status_t do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, - val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media) + val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) { dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val; dladm_status_t status; @@ -2362,6 +2314,50 @@ do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, return (status); } +/* ARGSUSED */ +static dladm_status_t +do_check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp, + datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp, + datalink_media_t media) +{ + int32_t hlim; + char *ep; + + if (val_cnt != 1) + return (DLADM_STATUS_BADVALCNT); + + errno = 0; + hlim = strtol(*prop_val, &ep, 10); + if (errno != 0 || ep == *prop_val || hlim < 1 || + hlim > (int32_t)UINT8_MAX) + return (DLADM_STATUS_BADVAL); + vdp->vd_val = hlim; + return (DLADM_STATUS_OK); +} + +/* ARGSUSED */ +static dladm_status_t +do_check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, + char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media) +{ + int32_t elim; + char *ep; + + if (media != DL_IPV6) + return (DLADM_STATUS_BADARG); + + if (val_cnt != 1) + return (DLADM_STATUS_BADVALCNT); + + errno = 0; + elim = strtol(*prop_val, &ep, 10); + if (errno != 0 || ep == *prop_val || elim < 0 || + elim > (int32_t)UINT8_MAX) + return (DLADM_STATUS_BADVAL); + vdp->vd_val = elim; + return (DLADM_STATUS_OK); +} + static dladm_status_t i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid, const char *prop_name, char **prop_val, uint_t val_cnt) diff --git a/usr/src/lib/libdladm/common/llib-ldladm b/usr/src/lib/libdladm/common/llib-ldladm index cc379d19b6..1020605a3c 100644 --- a/usr/src/lib/libdladm/common/llib-ldladm +++ b/usr/src/lib/libdladm/common/llib-ldladm @@ -31,6 +31,7 @@ #include <libdlwlan.h> #include <libdlvnic.h> #include <libdlvlan.h> +#include <libdliptun.h> #include <libdlmgmt.h> #include <libdlflow.h> #include <libdlstat.h> diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers index 048b809751..81b5d363cc 100644 --- a/usr/src/lib/libdladm/common/mapfile-vers +++ b/usr/src/lib/libdladm/common/mapfile-vers @@ -45,7 +45,6 @@ SUNWprivate_1.1 { dladm_door_fd; dladm_info; dladm_walk; - dladm_setzid; dladm_status2str; dladm_linkstate2str; dladm_linkduplex2str; @@ -108,6 +107,14 @@ SUNWprivate_1.1 { dladm_wlan_str2auth; dladm_wlan_str2bsstype; dladm_wlan_str2linkstatus; + dladm_iptun_create; + dladm_iptun_delete; + dladm_iptun_modify; + dladm_iptun_getparams; + dladm_iptun_up; + dladm_iptun_down; + dladm_iptun_set6to4relay; + dladm_iptun_get6to4relay; dladm_vlan_create; dladm_vlan_delete; dladm_vlan_up; @@ -156,6 +163,8 @@ SUNWprivate_1.1 { dladm_walk_usage_time; dladm_usage_summary; dladm_usage_dates; + dladm_zone_boot; + dladm_zone_halt; dladm_flow_add; dladm_flow_remove; diff --git a/usr/src/lib/libdladm/libdladm.xcl b/usr/src/lib/libdladm/libdladm.xcl index 5070c9457c..5e276923e8 100644 --- a/usr/src/lib/libdladm/libdladm.xcl +++ b/usr/src/lib/libdladm/libdladm.xcl @@ -43,9 +43,12 @@ msgid "0x" msgid "bridging" msgid "config" msgid "debug" +msgid "encaplimit" msgid "force-protocol" msgid "forward-delay" msgid "hello-time" +msgid "hoplimit" +msgid "iptun" msgid "max-age" msgid "nickname" msgid "r" diff --git a/usr/src/lib/libdlpi/common/libdlpi.c b/usr/src/lib/libdlpi/common/libdlpi.c index 2dcf98c90a..bda2648955 100644 --- a/usr/src/lib/libdlpi/common/libdlpi.c +++ b/usr/src/lib/libdlpi/common/libdlpi.c @@ -55,7 +55,6 @@ 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); -static int i_dlpi_remove_ppa(char *); static int i_dlpi_attach(dlpi_impl_t *); static void i_dlpi_passive(dlpi_impl_t *); @@ -134,7 +133,6 @@ int dlpi_open(const char *linkname, dlpi_handle_t *dhp, uint_t flags) { int retval, on = 1; - int cnt; ifspec_t ifsp; dlpi_impl_t *dip; @@ -166,14 +164,6 @@ dlpi_open(const char *linkname, dlpi_handle_t *dhp, uint_t flags) if (getenv("DLPI_DEVONLY") != NULL) dip->dli_oflags |= DLPI_DEVONLY; - if (!(flags & DLPI_DEVIPNET)) { - dip->dli_mod_cnt = ifsp.ifsp_modcnt; - for (cnt = 0; cnt != dip->dli_mod_cnt; cnt++) { - (void) strlcpy(dip->dli_modlist[cnt], - ifsp.ifsp_mods[cnt], DLPI_LINKNAME_MAX); - } - } - /* Copy linkname provided to the function. */ if (strlcpy(dip->dli_linkname, linkname, sizeof (dip->dli_linkname)) >= sizeof (dip->dli_linkname)) { @@ -1140,45 +1130,18 @@ i_dlpi_style1_open(dlpi_impl_t *dip) int retval, save_errno; int fd; - /* - * In order to support open of syntax like device[.module[.module...]] - * 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, B_TRUE); - - if (retval != DLPI_SUCCESS) { - dip->dli_mod_pushed = 0; + retval = i_dlpi_open(dip->dli_linkname, &fd, dip->dli_oflags, B_TRUE); + if (retval != DLPI_SUCCESS) return (retval); - } dip->dli_fd = fd; - /* - * Try to push modules (if any) onto the device stream. If I_PUSH - * fails, we increment count of modules pushed (dli_mod_pushed) - * expecting it is last module to be pushed and thus will be pushed - * in i_dlpi_style2_open(). - */ - for (dip->dli_mod_pushed = 0; dip->dli_mod_pushed < dip->dli_mod_cnt; - dip->dli_mod_pushed++) { - if (ioctl(fd, I_PUSH, - dip->dli_modlist[dip->dli_mod_pushed]) == -1) { - dip->dli_mod_pushed++; - return (DLPI_FAILURE); - } - } - if ((retval = i_dlpi_checkstyle(dip, DL_STYLE1)) != DLPI_SUCCESS) { save_errno = errno; (void) close(dip->dli_fd); errno = save_errno; - dip->dli_mod_pushed = 0; - return (retval); } - return (DLPI_SUCCESS); + return (retval); } /* @@ -1190,45 +1153,10 @@ i_dlpi_style2_open(dlpi_impl_t *dip) int fd; int retval, save_errno; - /* - * 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 - * open it as a style 2 link. - * - * If the pushing of the last module failed, we need to - * try pushing it as a style 2 module. Decrement dli_mod_pushed - * count so it can be pushed onto the stream. - * - * Otherwise we failed during the push of an intermediate module and - * must fail out and close the link. - */ - if (dip->dli_mod_pushed == 0) { - if ((retval = i_dlpi_open(dip->dli_provider, &fd, - 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]) - != DLPI_SUCCESS) - return (DLPI_ELINKNAMEINVAL); - - dip->dli_mod_pushed--; - fd = dip->dli_fd; - } else { - return (DLPI_ELINKNAMEINVAL); - } - - /* Try and push modules (if any) onto the device stream. */ - for (; dip->dli_mod_pushed < dip->dli_mod_cnt; dip->dli_mod_pushed++) { - if (ioctl(fd, I_PUSH, - dip->dli_modlist[dip->dli_mod_pushed]) == -1) { - retval = DL_SYSERR; - goto failure; - } - } + retval = i_dlpi_open(dip->dli_provider, &fd, dip->dli_oflags, B_FALSE); + if (retval != DLPI_SUCCESS) + return (retval); + dip->dli_fd = fd; /* * Special case: DLPI_SERIAL flag (synchronous serial lines) is not a @@ -1248,10 +1176,8 @@ i_dlpi_style2_open(dlpi_impl_t *dip) return (DLPI_SUCCESS); attach: - if ((retval = i_dlpi_attach(dip)) != DLPI_SUCCESS) - goto failure; - - return (DLPI_SUCCESS); + if ((retval = i_dlpi_attach(dip)) == DLPI_SUCCESS) + return (DLPI_SUCCESS); failure: save_errno = errno; @@ -1278,25 +1204,6 @@ i_dlpi_checkstyle(dlpi_impl_t *dip, t_uscalar_t style) } /* - * Remove PPA from end of linkname. - * Return DLPI_SUCCESS if found, else return DLPI_FAILURE. - */ -static int -i_dlpi_remove_ppa(char *linkname) -{ - int i = strlen(linkname) - 1; - - if (i == -1 || !isdigit(linkname[i--])) - return (DLPI_FAILURE); - - while (i >= 0 && isdigit(linkname[i])) - i--; - - linkname[i + 1] = '\0'; - return (DLPI_SUCCESS); -} - -/* * For DLPI style 2 providers, an explicit attach of PPA is required. */ static int @@ -1842,6 +1749,13 @@ i_dlpi_notifyind_process(dlpi_impl_t *dip, dl_notify_ind_t *dlnotifyindp) notifinfo.dni_size = dlnotifyindp->dl_data; break; case DL_NOTE_PHYS_ADDR: + /* + * libdlpi currently only supports notifications for + * DL_CURR_PHYS_ADDR. + */ + if (dlnotifyindp->dl_data != DL_CURR_PHYS_ADDR) + return (DLPI_ENOTENOTSUP); + dataoff = dlnotifyindp->dl_addr_offset; datalen = dlnotifyindp->dl_addr_length; diff --git a/usr/src/lib/libdlpi/common/libdlpi_impl.h b/usr/src/lib/libdlpi/common/libdlpi_impl.h index c1d61ff1f8..70708ff5af 100644 --- a/usr/src/lib/libdlpi/common/libdlpi_impl.h +++ b/usr/src/lib/libdlpi/common/libdlpi_impl.h @@ -19,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _LIBDLPI_IMPL_H #define _LIBDLPI_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <libdlpi.h> #include <sys/sysmacros.h> @@ -46,11 +44,6 @@ extern "C" { #define DLPI_SAPLEN_MAX 4 /* - * Maximum number of modules that can be pushed onto a device stream. - */ -#define DLPI_MODS_MAX 9 - -/* * Number of elements in 'arr'. */ #define NELEMS(arr) (sizeof (arr) / sizeof ((arr)[0])) @@ -124,10 +117,6 @@ typedef struct dlpi_impl_s { uint_t dli_sap; /* bound SAP value */ boolean_t dli_sapbefore; /* true if SAP precedes address */ uint_t dli_ppa; /* physical point of attachment */ - uint_t dli_mod_cnt; /* number of modules to be pushed */ - uint_t dli_mod_pushed; /* number of modules pushed */ - char dli_modlist[DLPI_MODS_MAX][DLPI_LINKNAME_MAX]; - /* array of mods */ uint_t dli_mactype; /* mac type */ uint_t dli_oflags; /* flags set at open */ uint_t dli_note_processing; diff --git a/usr/src/lib/libinetcfg/common/inetcfg.c b/usr/src/lib/libinetcfg/common/inetcfg.c index e1f09a881a..d5a27f23ea 100644 --- a/usr/src/lib/libinetcfg/common/inetcfg.c +++ b/usr/src/lib/libinetcfg/common/inetcfg.c @@ -44,9 +44,6 @@ #define ICFG_FAMILY(handle) handle->ifh_interface.if_protocol -#define ICFG_TUNNEL_PROTOCOL(protocol) \ - (protocol == IFTAP_IPV6) ? AF_INET6 : AF_INET - #define ICFG_SOCKADDR_LEN(protocol) \ (protocol == AF_INET) ? \ (socklen_t)sizeof (struct sockaddr_in) : \ @@ -66,12 +63,11 @@ static char *errmsgs[ICFG_NERR] = { /* 0 ICFG_SUCCESS */ "Success", /* 1 ICFG_FAILURE */ "Failure", -/* 2 ICFG_NOT_TUNNEL */ "Tunnel operation attempted on non-tunnel", -/* 3 ICFG_NOT_SET */ "Could not return non-existent value", -/* 4 ICFG_BAD_ADDR */ "Invalid Address", -/* 5 ICFG_BAD_PROT */ "Wrong protocol family for operation", -/* 6 ICFG_DAD_FAILED */ "Duplicate address detection failure", -/* 7 ICFG_DAD_FOUND */ "Duplicate address detected" +/* 2 ICFG_NOT_SET */ "Could not return non-existent value", +/* 3 ICFG_BAD_ADDR */ "Invalid Address", +/* 4 ICFG_BAD_PROT */ "Wrong protocol family for operation", +/* 5 ICFG_DAD_FAILED */ "Duplicate address detection failure", +/* 6 ICFG_DAD_FOUND */ "Duplicate address detected" }; /* @@ -156,110 +152,6 @@ to_sockaddr_storage(sa_family_t af, const struct sockaddr *addr, } /* - * Ensures that the tunnel parameter data for the tunnel associated with - * the handle is cached. If the 'force_update' argument is TRUE, then the - * cache should be updated. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -static int -get_tunnel_params(icfg_handle_t handle, boolean_t force_update) -{ - struct iftun_req *params; - - if ((handle->ifh_tunnel_params != NULL) && (!force_update)) { - return (ICFG_SUCCESS); - } - - if (strchr(handle->ifh_interface.if_name, ICFG_LOGICAL_SEP) != NULL) { - return (ICFG_NOT_TUNNEL); - } - - if ((params = calloc(1, sizeof (struct iftun_req))) == NULL) { - return (ICFG_FAILURE); - } - - (void) strlcpy(params->ifta_lifr_name, handle->ifh_interface.if_name, - sizeof (params->ifta_lifr_name)); - - if (ioctl(handle->ifh_sock, SIOCGTUNPARAM, (caddr_t)params) < 0) { - free(params); - if ((errno == EOPNOTSUPP) || (errno == EINVAL)) { - return (ICFG_NOT_TUNNEL); - } - return (ICFG_FAILURE); - } - - /* - * We assert that the iftun_req version is the right one - * and that the lower and upper protocols are set to either - * IPv4 or IPv6. Otherwise, some of our APIs are buggy. - */ - assert((params->ifta_vers == IFTUN_VERSION) && - ((params->ifta_lower == IFTAP_IPV4) || - (params->ifta_lower == IFTAP_IPV6)) && - ((params->ifta_upper == IFTAP_IPV4) || - (params->ifta_upper == IFTAP_IPV6))); - - if (handle->ifh_tunnel_params != NULL) { - free(handle->ifh_tunnel_params); - } - handle->ifh_tunnel_params = params; - - return (ICFG_SUCCESS); -} - -/* - * Sets a tunnel destination or source address (depending upon 'type') on - * a tunnel interface. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -static int -set_tunnel_address(icfg_handle_t handle, const struct sockaddr *addr, - socklen_t addrlen, int type) -{ - struct sockaddr_storage laddr; - sa_family_t lower_family; - struct iftun_req *params; - int ret; - - assert((type == IFTUN_SRC) || (type == IFTUN_DST)); - - if ((ret = get_tunnel_params(handle, B_TRUE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - if (params->ifta_lower == IFTAP_IPV4) { - lower_family = AF_INET; - } else { - lower_family = AF_INET6; - } - - ret = to_sockaddr_storage(lower_family, addr, addrlen, &laddr); - if (ret != ICFG_SUCCESS) { - return (ret); - } - - if (type == IFTUN_SRC) { - params->ifta_saddr = laddr; - } else { - params->ifta_daddr = laddr; - } - - (void) strlcpy(params->ifta_lifr_name, handle->ifh_interface.if_name, - sizeof (params->ifta_lifr_name)); - params->ifta_flags |= type; - - if (ioctl(handle->ifh_sock, SIOCSTUNPARAM, (caddr_t)params) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* * Return the appropriate error message for a given ICFG error. */ const char * @@ -311,7 +203,6 @@ icfg_open(icfg_handle_t *handle, const icfg_if_t *interface) loc_handle->ifh_sock = sock; loc_handle->ifh_interface = *interface; - loc_handle->ifh_tunnel_params = NULL; *handle = loc_handle; @@ -326,351 +217,10 @@ void icfg_close(icfg_handle_t handle) { (void) close(handle->ifh_sock); - if (handle->ifh_tunnel_params != NULL) { - free(handle->ifh_tunnel_params); - } free(handle); } /* - * Refreshes the tunnel parameter data cache associated with the interface - * represented by the handle. Tunnel parameter data is cached by the - * libinetcfg library by the first call to to any of the tunnel related APIs. - * Since there is no synchronization between consumers of the library and - * non-users of this library, the cache may contain stale data. Users may - * wish to use this API to refresh the cache before subsequent calls to the - * other tunnel related APIs. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -int -icfg_refresh_tunnel_cache(icfg_handle_t handle) -{ - return (get_tunnel_params(handle, B_TRUE)); -} - -/* - * Sets the destination address for the tunnel interface represented - * by 'handle'. - * - * The 'addr' argument points to either a sockaddr_in structure - * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds - * the IP address. The 'addrlen' argument gives the length of the - * 'addr' structure. - * - * This API will always result in an update of the tunnel parameter - * data cache. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -int -icfg_set_tunnel_dest(icfg_handle_t handle, const struct sockaddr *addr, - socklen_t addrlen) -{ - return (set_tunnel_address(handle, addr, addrlen, IFTUN_DST)); -} - -/* - * Sets the source address for the tunnel interface represented - * by 'handle'. - * - * The 'addr' argument points to either a sockaddr_in structure - * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds - * the IP address. The 'addrlen' argument gives the length of the - * 'addr' structure. - * - * This API will always result in an update of the tunnel parameter - * data cache. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -int -icfg_set_tunnel_src(icfg_handle_t handle, const struct sockaddr *addr, - socklen_t addrlen) -{ - return (set_tunnel_address(handle, addr, addrlen, IFTUN_SRC)); -} - -/* - * Sets the hop limit for the tunnel interface represented by - * the handle to the value contained in the 'limit' argument. - * - * This API will always result in an update of the tunnel parameter data cache. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -int -icfg_set_tunnel_hoplimit(icfg_handle_t handle, uint8_t limit) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_TRUE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - (void) strlcpy(params->ifta_lifr_name, handle->ifh_interface.if_name, - sizeof (params->ifta_lifr_name)); - - params->ifta_hop_limit = limit; - params->ifta_flags |= IFTUN_HOPLIMIT; - - if (ioctl(handle->ifh_sock, SIOCSTUNPARAM, (caddr_t)params) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the encapsulation limit for the tunnel interface represented by - * the handle to the value contained in the 'limit' argument. If the - * value of the limit is negative, then the encapsulation limit is disabled. - * - * This API will always result in an update of the tunnel parameter data cache. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -int -icfg_set_tunnel_encaplimit(icfg_handle_t handle, int16_t limit) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_TRUE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - (void) strlcpy(params->ifta_lifr_name, handle->ifh_interface.if_name, - sizeof (params->ifta_lifr_name)); - - params->ifta_encap_lim = limit; - params->ifta_flags |= IFTUN_ENCAP; - - if (ioctl(handle->ifh_sock, SIOCSTUNPARAM, (caddr_t)params) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Returns the source address for the tunnel interface represented - * by 'handle'. - * - * The 'addr' argument is a result parameter that is filled in with - * the requested address. The format of the 'addr' parameter is - * determined by the address family of the interface. - * - * The 'addrlen' argument is a value-result parameter. Initially, - * it contains the amount of space pointed to by 'addr'; on return - * it contains the length in bytes of the address returned. - * - * Note that if 'addrlen' is not large enough for the returned - * address value, then ICFG_FAILURE will be returned and errno - * will be set to ENOSPC. - * - * This API will retrieve the tunnel source value from the tunnel - * parameter data cache and will only update the cache if no data has - * yet been cached for this tunnel. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL, ICFG_NOT_SET or - * ICFG_FAILURE. - */ -int -icfg_get_tunnel_src(icfg_handle_t handle, struct sockaddr *addr, - socklen_t *addrlen) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_FALSE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - if (!(params->ifta_flags & IFTUN_SRC)) { - return (ICFG_NOT_SET); - } - - if (params->ifta_lower == IFTAP_IPV4) { - assert(params->ifta_saddr.ss_family == AF_INET); - } else { - assert(params->ifta_saddr.ss_family == AF_INET6); - } - - return (to_sockaddr(params->ifta_saddr.ss_family, addr, addrlen, - ¶ms->ifta_saddr)); -} - -/* - * Returns the destination address for the tunnel interface - * represented by 'handle'. - * - * The 'addr' argument is a result parameter that is filled in - * with the requested address. The format of the 'addr' parameter - * is determined by the address family of the interface. - * - * The 'addrlen' argument is a value-result parameter. Initially, it - * contains the amount of space pointed to by 'addr'; on return it - * contains the length in bytes of the address returned. - * - * Note that if 'addrlen' is not large enough for the returned address - * value, then ICFG_FAILURE will be returned and errno will be set - * to ENOSPC. - * - * This API will retrieve the tunnel destination value from the tunnel - * parameter data cache and will only update the cache if no data has yet - * been cached for this tunnel. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL, ICFG_NOT_SET or - * ICFG_FAILURE. - */ -int -icfg_get_tunnel_dest(icfg_handle_t handle, struct sockaddr *addr, - socklen_t *addrlen) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_FALSE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - if (!(params->ifta_flags & IFTUN_DST)) { - return (ICFG_NOT_SET); - } - - if (params->ifta_lower == IFTAP_IPV4) { - assert(params->ifta_daddr.ss_family == AF_INET); - } else if (params->ifta_lower == IFTAP_IPV6) { - assert(params->ifta_daddr.ss_family == AF_INET6); - } - - return (to_sockaddr(params->ifta_daddr.ss_family, addr, addrlen, - ¶ms->ifta_daddr)); -} - -/* - * Returns the tunnel hop limit (if any). The value of the limit - * will be copied into the buffer supplied by the 'limit' argument. - * - * This API will retrieve the hoplimit value from the tunnel parameter data - * cache and will only update the cache if no data has yet been cached for - * this tunnel. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL, ICFG_NOT_SET or - * ICFG_FAILURE. - */ -int -icfg_get_tunnel_hoplimit(icfg_handle_t handle, uint8_t *limit) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_FALSE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - if (!(params->ifta_flags & IFTUN_HOPLIMIT)) { - return (ICFG_NOT_SET); - } - - *limit = params->ifta_hop_limit; - - return (ICFG_SUCCESS); -} - -/* - * Returns the tunnel encapsulation limit (if any). The value of the limit - * will be copied into the buffer supplied by the 'limit' argument. - * - * This API will retrieve the encapsulation limit value from the tunnel - * parameter data cache and will only update the cache if no data has yet - * been cached for this tunnel. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL, ICFG_NOT_SET or - * ICFG_FAILURE. - */ -int -icfg_get_tunnel_encaplimit(icfg_handle_t handle, int16_t *limit) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_FALSE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - if (!(params->ifta_flags & IFTUN_ENCAP)) { - return (ICFG_NOT_SET); - } - - *limit = params->ifta_encap_lim; - - return (ICFG_SUCCESS); -} - -/* - * Returns the protocol family (AF_INET or AF_INET6) of the protocol - * actually being used to tunnel the data. The value of the protocol family - * will be copied into the buffer supplied by the 'protocol' argument. - * - * This API will retrieve the protocol value from the tunnel parameter data - * cache and will only update the cache if no data has yet been cached for - * this tunnel. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -int -icfg_get_tunnel_lower(icfg_handle_t handle, int *protocol) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_FALSE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - *protocol = ICFG_TUNNEL_PROTOCOL(params->ifta_lower); - - return (ICFG_SUCCESS); -} - -/* - * Returns the protocol family (AF_INET or AF_INET6) of the protocol - * actually being tunneled. The value of the protocol family will be copied - * into the buffer supplied by the 'protocol' argument. - * - * This API will retrieve the protocolvalue from the tunnel parameter data - * cache and will only update the cache if no data has yet been cached for - * this tunnel. - * - * Returns: ICFG_SUCCESS, ICFG_NOT_TUNNEL or ICFG_FAILURE. - */ -int -icfg_get_tunnel_upper(icfg_handle_t handle, int *protocol) -{ - struct iftun_req *params; - int ret; - - if ((ret = get_tunnel_params(handle, B_FALSE)) != ICFG_SUCCESS) { - return (ret); - } - params = handle->ifh_tunnel_params; - - *protocol = ICFG_TUNNEL_PROTOCOL(params->ifta_upper); - - return (ICFG_SUCCESS); -} - -/* * Any time that flags are changed on an interface where either the new or the * existing flags have IFF_UP set, we'll get at least one RTM_IFINFO message to * announce the flag status. Typically, there are two such messages: one diff --git a/usr/src/lib/libinetcfg/common/inetcfg.h b/usr/src/lib/libinetcfg/common/inetcfg.h index 323fc09b95..fad1b9b0ca 100644 --- a/usr/src/lib/libinetcfg/common/inetcfg.h +++ b/usr/src/lib/libinetcfg/common/inetcfg.h @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _INETCFG_H #define _INETCFG_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> @@ -40,12 +37,11 @@ extern "C" { /* error codes */ #define ICFG_SUCCESS 0 /* API was successful */ #define ICFG_FAILURE 1 /* Generic failure */ -#define ICFG_NOT_TUNNEL 2 /* Tunnel operation attempted on non-tunnel */ -#define ICFG_NOT_SET 3 /* Could not return non-existent value */ -#define ICFG_BAD_ADDR 4 /* Invalid address */ -#define ICFG_BAD_PROT 5 /* Wrong protocol family for operation */ -#define ICFG_DAD_FAILED 6 /* Duplicate address detection failure */ -#define ICFG_DAD_FOUND 7 /* Duplicate address detected */ +#define ICFG_NOT_SET 2 /* Could not return non-existent value */ +#define ICFG_BAD_ADDR 3 /* Invalid address */ +#define ICFG_BAD_PROT 4 /* Wrong protocol family for operation */ +#define ICFG_DAD_FAILED 5 /* Duplicate address detection failure */ +#define ICFG_DAD_FOUND 6 /* Duplicate address detected */ #define ICFG_NERR (ICFG_DAD_FOUND + 1) @@ -61,25 +57,11 @@ typedef struct icfg_if { typedef struct icfg_handle { int ifh_sock; /* socket to interface */ icfg_if_t ifh_interface; /* interface definition */ - struct iftun_req *ifh_tunnel_params; /* tunnel parameters */ } *icfg_handle_t; extern const char *icfg_errmsg(int); extern int icfg_open(icfg_handle_t *, const icfg_if_t *); extern void icfg_close(icfg_handle_t); -extern int icfg_refresh_tunnel_cache(icfg_handle_t); -extern int icfg_set_tunnel_dest(icfg_handle_t, const struct sockaddr *, - socklen_t); -extern int icfg_set_tunnel_src(icfg_handle_t, const struct sockaddr *, - socklen_t); -extern int icfg_set_tunnel_hoplimit(icfg_handle_t, uint8_t); -extern int icfg_set_tunnel_encaplimit(icfg_handle_t, int16_t); -extern int icfg_get_tunnel_dest(icfg_handle_t, struct sockaddr *, socklen_t *); -extern int icfg_get_tunnel_src(icfg_handle_t, struct sockaddr *, socklen_t *); -extern int icfg_get_tunnel_hoplimit(icfg_handle_t, uint8_t *); -extern int icfg_get_tunnel_encaplimit(icfg_handle_t, int16_t *); -extern int icfg_get_tunnel_lower(icfg_handle_t, int *); -extern int icfg_get_tunnel_upper(icfg_handle_t, int *); extern int icfg_set_flags(icfg_handle_t, uint64_t); extern int icfg_set_metric(icfg_handle_t, int); extern int icfg_set_mtu(icfg_handle_t, uint_t); diff --git a/usr/src/lib/libinetcfg/common/mapfile-vers b/usr/src/lib/libinetcfg/common/mapfile-vers index b8ea188f89..3ecc82bd63 100644 --- a/usr/src/lib/libinetcfg/common/mapfile-vers +++ b/usr/src/lib/libinetcfg/common/mapfile-vers @@ -54,16 +54,9 @@ SUNWprivate_1.1 { icfg_get_netmask; icfg_get_subnet; icfg_get_token; - icfg_get_tunnel_dest; - icfg_get_tunnel_encaplimit; - icfg_get_tunnel_hoplimit; - icfg_get_tunnel_lower; - icfg_get_tunnel_src; - icfg_get_tunnel_upper; icfg_is_logical; icfg_iterate_if; icfg_open; - icfg_refresh_tunnel_cache; icfg_set_addr; icfg_set_broadcast; icfg_set_dest_addr; @@ -75,10 +68,6 @@ SUNWprivate_1.1 { icfg_set_prefixlen; icfg_set_subnet; icfg_set_token; - icfg_set_tunnel_dest; - icfg_set_tunnel_encaplimit; - icfg_set_tunnel_hoplimit; - icfg_set_tunnel_src; icfg_sockaddr_to_str; icfg_str_to_sockaddr; local: diff --git a/usr/src/lib/libinetutil/common/ifspec.c b/usr/src/lib/libinetutil/common/ifspec.c index 157b497efd..7cf41591c5 100644 --- a/usr/src/lib/libinetutil/common/ifspec.c +++ b/usr/src/lib/libinetutil/common/ifspec.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * This file contains a routine used to validate a ifconfig-style interface * specification @@ -92,7 +90,7 @@ getppa(const char *bp, int bpsize, uint_t *ppa) for (tp = ep; tp >= bp && isdigit(*tp); tp--) /* Null body */; - if (*tp == '.' || *tp == ':') { + if (*tp == ':') { errno = EINVAL; return (-1); } @@ -103,75 +101,34 @@ getppa(const char *bp, int bpsize, uint_t *ppa) /* * Given an ifconfig-style inet relative-path interface specification - * (e.g: hme.[module].[module][PPA]:2), validate its form and decompose the - * contents into a dynamically allocated ifspec_t. + * (e.g: bge0:2), validate its form and decompose the contents into a + * dynamically allocated ifspec_t. * * Returns ifspec_t for success, NULL pointer if spec is malformed. */ boolean_t ifparse_ifspec(const char *ifname, ifspec_t *ifsp) { - char *mp, *ep, *lp, *tp; - char *ifnamecp; - size_t iflen; - boolean_t have_ppa = B_FALSE; + char *lp, *tp; + char ifnamecp[LIFNAMSIZ]; - iflen = strlen(ifname); - if (iflen > LIFNAMSIZ) { + /* snag a copy we can modify */ + if (strlcpy(ifnamecp, ifname, LIFNAMSIZ) >= LIFNAMSIZ) { errno = EINVAL; return (B_FALSE); } - /* snag a copy we can modify */ - ifnamecp = alloca(iflen + 1); - (void) strlcpy(ifnamecp, ifname, iflen + 1); - ifsp->ifsp_lunvalid = B_FALSE; /* * An interface name must have the format of: - * dev[.module[.module...]][ppa][:lun] - * - * where the ppa must be specified at the end of the interface name. - * e.g. ip.foo.tun0 + * dev[ppa][:lun] * * lun - logical unit number. - * - * Produce substrings for each grouping, starting first with modules, - * then lun, devname, and finally ppa. */ - /* Any modules? */ - mp = strchr(ifnamecp, '.'); - /* Any logical units? */ lp = strchr(ifnamecp, ':'); - - if (lp != NULL && mp != NULL && lp < mp) { - errno = EINVAL; - return (B_FALSE); - } - - ifsp->ifsp_modcnt = 0; - if (mp != NULL) { - *mp++ = '\0'; - if (lp != NULL) - *lp = '\0'; - while (mp != NULL && ifsp->ifsp_modcnt <= IFSP_MAXMODS) { - if ((ep = strchr(mp, '.')) != NULL) - *ep++ = '\0'; - (void) strlcpy(ifsp->ifsp_mods[ifsp->ifsp_modcnt++], - mp, LIFNAMSIZ); - mp = ep; - } - if (lp != NULL) - *lp = ':'; - if (ifsp->ifsp_modcnt > IFSP_MAXMODS) { - errno = E2BIG; - return (B_FALSE); - } - } - if (lp != NULL) { if (getlun(lp, strlen(lp), &ifsp->ifsp_lun) != 0) return (B_FALSE); @@ -180,25 +137,17 @@ ifparse_ifspec(const char *ifname, ifspec_t *ifsp) (void) strlcpy(ifsp->ifsp_devnm, ifnamecp, LIFNAMSIZ); - /* - * Find ppa - has to be part of devname or if modules exist part of - * last module name. - */ - if (ifsp->ifsp_modcnt != 0 && - getppa(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1], - strlen(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1]), - &ifsp->ifsp_ppa) == 0) { - have_ppa = B_TRUE; - } else if (ifsp->ifsp_modcnt == 0 && - getppa(ifsp->ifsp_devnm, strlen(ifsp->ifsp_devnm), - &ifsp->ifsp_ppa) == 0) { - have_ppa = B_TRUE; - - /* strip the ppa off of the device name if present */ - for (tp = &ifsp->ifsp_devnm[strlen(ifsp->ifsp_devnm) - 1]; - tp >= ifsp->ifsp_devnm && isdigit(*tp); tp--) - *tp = '\0'; + /* Find ppa */ + if (getppa(ifsp->ifsp_devnm, strlen(ifsp->ifsp_devnm), + &ifsp->ifsp_ppa) != 0) { + return (B_FALSE); + } + + /* strip the ppa off of the device name if present */ + for (tp = &ifsp->ifsp_devnm[strlen(ifsp->ifsp_devnm) - 1]; + tp >= ifsp->ifsp_devnm && isdigit(*tp); tp--) { + *tp = '\0'; } - return (have_ppa); + return (B_TRUE); } diff --git a/usr/src/lib/libinetutil/common/libinetutil.h b/usr/src/lib/libinetutil/common/libinetutil.h index 0bece07e07..bacf64938a 100644 --- a/usr/src/lib/libinetutil/common/libinetutil.h +++ b/usr/src/lib/libinetutil/common/libinetutil.h @@ -43,15 +43,11 @@ extern "C" { #if !defined(_KERNEL) && !defined(_BOOT) -#define IFSP_MAXMODS 9 /* Max modules that can be pushed on if */ - typedef struct { uint_t ifsp_ppa; /* Physical Point of Attachment */ uint_t ifsp_lun; /* Logical Unit number */ boolean_t ifsp_lunvalid; /* TRUE if lun is valid */ - int ifsp_modcnt; /* Number of modules to be pushed */ char ifsp_devnm[LIFNAMSIZ]; /* only the device name */ - char ifsp_mods[IFSP_MAXMODS][LIFNAMSIZ]; /* table of mods */ } ifspec_t; extern boolean_t ifparse_ifspec(const char *, ifspec_t *); diff --git a/usr/src/lib/libinetutil/common/ofmt.c b/usr/src/lib/libinetutil/common/ofmt.c index 2f9fe3f91d..ccae05091c 100644 --- a/usr/src/lib/libinetutil/common/ofmt.c +++ b/usr/src/lib/libinetutil/common/ofmt.c @@ -167,11 +167,12 @@ splitfree(split_t *sp) * Open a handle to be used for printing formatted output. */ ofmt_status_t -ofmt_open(const char *str, ofmt_field_t *template, uint_t flags, +ofmt_open(const char *str, const ofmt_field_t *template, uint_t flags, uint_t maxcols, ofmt_handle_t *ofmt) { split_t *sp; uint_t i, j, of_index; + const ofmt_field_t *ofp; ofmt_field_t *of; ofmt_state_t *os; int nfields = 0; @@ -192,7 +193,7 @@ ofmt_open(const char *str, ofmt_field_t *template, uint_t flags, } if (template == NULL) return (OFMT_ENOTEMPLATE); - for (of = template; of->of_name != NULL; of++) + for (ofp = template; ofp->of_name != NULL; ofp++) nfields++; /* * split str into the columns selected, or construct the diff --git a/usr/src/lib/libinetutil/common/ofmt.h b/usr/src/lib/libinetutil/common/ofmt.h index ff03b80ae0..a477847917 100644 --- a/usr/src/lib/libinetutil/common/ofmt.h +++ b/usr/src/lib/libinetutil/common/ofmt.h @@ -165,7 +165,7 @@ typedef struct ofmt_field_s { * for the handle are freed by ofmt_close(); */ typedef struct ofmt_state_s *ofmt_handle_t; -extern ofmt_status_t ofmt_open(const char *, ofmt_field_t *, uint_t, +extern ofmt_status_t ofmt_open(const char *, const ofmt_field_t *, uint_t, uint_t, ofmt_handle_t *); #define OFMT_PARSABLE 0x00000001 /* machine parsable mode */ |