/*
* 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
* 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
*/
/*
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <alloca.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <fcntl.h>
#include <unistd.h>
#include <libdlpi.h>
#include <libdladm.h>
#include <libdllink.h>
#include <zone.h>
#include <net/if_types.h>
#include <netdb.h>
#include <rad/radclient.h>
#include "netlink-protocol.h"
#include "netlink.h"
#include "flow.h"
#include "packets.h"
#include "util-solaris.h"
#include "util.h"
#include "dpif-solaris.h"
#ifndef MAX_OF_ACTIONS_SIZE
#endif
typedef struct {
} ifspec_t;
typedef struct {
static int
{
char *ep;
unsigned long ul;
errno = 0;
return (-1);
return (0);
}
/*
* Given a token with a logical unit spec, return the logical unit converted
* to a uint_t.
*
* Returns: 0 for success, nonzero if an error occurred. errno is set if
* necessary.
*/
static int
{
const char *tp;
/* Lun must be all digits */
/* Null body */;
return (-1);
}
return (0);
}
/*
* Given a single token ending with a ppa spec, return the ppa spec converted
* to a uint_t.
*
* Returns: 0 for success, nonzero if an error occurred. errno is set if
* necessary.
*/
static int
{
const char *tp;
/* Null body */;
/*
* If the device name does not end with a digit or the device
* name is a sequence of numbers or a PPA contains a leading
* zero, return error.
*/
goto fail;
goto fail;
/* max value of PPA is 4294967294, which is (UINT_MAX - 1) */
goto fail;
return (0);
fail:
return (-1);
}
/*
* Given a `linkname' of the form drv(ppa), parse it into `driver' and `ppa'.
* If the `dsize' for the `driver' is not atleast MAXLINKNAMELEN then part of
* the driver name will be copied to `driver'.
*
* This function also validates driver name and PPA and therefore callers can
* call this function with `driver' and `ppa' set to NULL, to just verify the
* linkname.
*/
{
char *tp;
goto fail;
if (len >= MAXLINKNAMELEN)
goto fail;
/* Get PPA */
return (_B_FALSE);
/* strip the ppa off of the linkname, if present */
*tp = '\0';
/*
* Now check for the validity of the device name. The legal characters
* in a device name are: alphanumeric (a-z, A-Z, 0-9), underscore
* ('_'), hyphen ('-'), and period ('.'). The first character
* of the device name cannot be a digit and should be an alphabetic
* character.
*/
goto fail;
goto fail;
}
return (_B_TRUE);
fail:
return (_B_FALSE);
}
/*
* Given an IP interface name, which is either a
* - datalink name (which is driver name plus PPA), for e.g. bge0 or
* - datalink name plus a logical interface identifier (delimited by ':'),
* for e.g. bge0:34
* the following function validates its form and decomposes the contents into
* ifspec_t.
*
* Returns _B_TRUE for success, otherwise _B_FALSE is returned.
*/
static boolean_t
{
char *lp;
return (_B_FALSE);
}
/* Any logical units? */
return (_B_FALSE);
*lp = '\0';
}
}
/*
* Issues the ioctl SIOCSLIFNAME to kernel.
*/
static int
{
int status = 0;
/* We should have already validated the interface name. */
}
return (status);
}
/*
* Wrapper for sending a non-transparent I_STR ioctl().
* Returns: Result from ioctl().
*/
static int
{
}
/*
* Issues the ioctl SIOCSLIFNAME to kernel on the given ARP stream fd.
*/
static int
{
/*
* Tell ARP the name and unit number for this interface.
* Note that arp has no support for transparent ioctls.
*/
sizeof (lifr)) == -1) {
return (errno);
}
return (0);
}
/*
* the bottom of the stream for tunneling interfaces.
*/
static int
{
int err;
return (errno);
/*
* Pop off all undesired modules (note that the user may have
* configured autopush to add modules above udp), and push the
* arp module onto the resulting stream. This is used to make
* IP+ARP be able to atomically track the muxid for the I_PLINKed
* STREAMS, thus it isn't related to ARP running the ARP protocol.
*/
;
return (0);
return (err);
}
static char *
{
if (protocol == IPPROTO_TCP)
return ("tcp");
if (protocol == IPPROTO_UDP)
return ("udp");
if (protocol == IPPROTO_SCTP)
return ("sctp");
if (protocol == IPPROTO_ICMPV6)
return ("icmpv6");
if (protocol == IPPROTO_ICMP)
return ("icmp");
else
return ("");
}
static uint8_t
{
return (IPPROTO_TCP);
return (IPPROTO_UDP);
return (IPPROTO_SCTP);
return (IPPROTO_ICMPV6);
return (IPPROTO_ICMP);
return (0);
}
/*
* Returns the flags value for the logical interface in `lifname'
* in the buffer pointed to by `flags'.
*/
static int
{
return (errno);
return (0);
}
/*
* For a given interface name, checks if IP interface exists.
*/
int
{
int error = 0;
return (error);
}
int
{
int ip_muxid;
int arp_muxid;
char *udp_dev_name;
int ret = 0;
/*
* the same now for PUNLINK also.
*/
goto done;
}
if (ret != 0)
goto done;
goto done;
}
if (ret != 0)
goto done;
/*
* We don't have a good way of knowing whether the arp stream is
* plumbed. We can't rely on IFF_NOARP because someone could
* have turned it off later using "ifconfig xxx -arp".
*/
if (arp_muxid != 0) {
/*
* Some plumbing utilities set the muxid to
* -1 or some invalid value to signify that
* there is no arp stream. Set the muxid to 0
* before trying to unplumb the IP stream.
* IP does not allow the IP stream to be
* unplumbed if it sees a non-null arp muxid,
* for consistency of IP-ARP streams.
*/
lifr.lifr_arp_muxid = 0;
}
}
}
if (changed_arp_muxid) {
/*
* Some error occurred, and we need to restore
* everything back to what it was.
*/
}
}
done:
if (muxid_fd != -1)
if (mux_fd != -1)
return (ret);
}
/*
* Plumbs the interface `ifname'.
*/
int
{
int ip_muxid;
char *udp_dev_name;
int status = 0;
const char *linkname;
int ret;
goto done;
}
/*
* We use DLPI_NOATTACH because the ip module will do the attach
* itself for DLPI style-2 devices.
*/
if (ret != DLPI_SUCCESS) {
goto done;
}
goto done;
}
} else {
}
if (status != 0)
goto done;
/* Get the full set of existing flags for this stream */
if (status != 0)
goto done;
if (status != 0)
goto done;
/* Check if arp is not needed */
/*
* PLINK the interface stream so that the application can exit
* without tearing down the stream.
*/
goto done;
}
/*
* This interface does use ARP, so set up a separate stream
* from the interface to ARP.
*
* We use DLPI_NOATTACH because the arp module will do the attach
* itself for DLPI style-2 devices.
*/
if (ret != DLPI_SUCCESS) {
goto done;
}
goto done;
}
if (status != 0)
goto done;
/*
* PLINK the IP and ARP streams so that we can exit
* without tearing down the stream.
*/
goto done;
}
}
done:
if (mux_fd != -1)
return (status);
}
int
{
return (ENODEV); /* Not sure what to return */
return (ENODEV); /* Not sure what to return */
}
return (0);
}
static rc_err_t
{
return (RCE_OK);
}
static rc_err_t
{
}
return (RCE_OK);
}
static int
{
int error = 0;
"name", netdev_name);
goto out;
}
if (status == RCE_SERVER_OBJECT) {
"failed Datalink_getInfo(%s): %s",
}
goto out;
}
propstr[0] = '\0';
propstr);
goto out;
}
out:
return (error);
}
int
{
int error = 0;
"name", netdev_name);
goto out;
}
if (status == RCE_SERVER_OBJECT) {
"failed Physical_getInfo(%s): %s",
}
goto out;
}
&dlval);
goto out;
}
out:
return (error);
}
int
{
test_dlclass));
}
int
{
test_dllower));
}
int
{
int ndlist = 0;
int error = 0, i = 0;
"name", netdev_name);
goto out;
}
fields[0] = field_name;
if (status == RCE_SERVER_OBJECT) {
"failed Datalink_getProperties(%s, %s): %s",
}
goto out;
}
field_name, &dlval);
goto out;
}
case DDLVT_STRING:
goto out;
}
break;
case DDLVT_STRINGS:
if (dlval->ddlv_slist_count == 0) {
goto out;
}
for (i = 0; i < dlval->ddlv_slist_count; i++) {
}
break;
case DDLVT_ULONG:
goto out;
}
break;
case DDLVT_BOOLEAN:
goto out;
}
break;
case DDLVT_BOOLEANS:
case DDLVT_LONG:
case DDLVT_LONGS:
case DDLVT_ULONGS:
case DDLVT_DICTIONARY:
case DDLVT_DICTIONARYS:
default:
ovs_assert(0);
break;
}
out:
return (error);
}
static int
{
int error = 0;
"name", netdev_name);
goto out;
}
if (sprop_dict == NULL) {
goto out;
}
switch (vtype) {
case DDLVT_BOOLEAN:
goto out;
}
break;
case DDLVT_ULONG:
goto out;
}
break;
case DDLVT_STRING:
goto out;
}
break;
case DDLVT_LONG:
case DDLVT_LONGS:
case DDLVT_ULONGS:
case DDLVT_STRINGS:
case DDLVT_BOOLEANS:
case DDLVT_DICTIONARY:
case DDLVT_DICTIONARYS:
default:
ovs_assert(0);
break;
}
if (temp) {
goto out;
}
}
if (status == RCE_SERVER_OBJECT) {
"failed Datalink_setPropertiess(%s, %s): %s",
}
}
out:
return (error);
}
int
{
temp));
}
int
{
temp));
}
int
{
temp));
}
static int
{
return (EINVAL);
}
if (dstr)
}
return (0);
}
static int
{
return (EINVAL);
}
}
return (0);
}
int
{
&linkmgr, 0);
goto out;
goto out;
/* linkname is 'const char *' and ddlv_sval is 'char *' */
goto out;
if (status == RCE_SERVER_OBJECT) {
"failed DatalinkManager_createVNIC(%s): %s",
}
out:
}
/*
* Try setting implicit VNIC's mac-addr-type as "fixed", if it fails then try
* with "auto" else bail out. This procedure is to ensure vnic migration
* succeeds specifically on LDOM's vnet (ensuring it works on other uplinks too)
*/
int
{
int error = 0;
"name", vnicname);
goto out;
}
if (sprop_dict == NULL) {
goto out;
}
if (mac_info_dict == NULL) {
goto out;
}
goto out;
}
mac_address, sizeof (mac_address))) != 0) {
goto out;
}
"fixed", NULL, 0)) != 0) {
goto out;
}
mac_address, NULL, 0)) != 0) {
goto out;
}
mac_info_dict)) != 0) {
goto out;
}
/* If it fails with "fixed" as mac-addr-type, try with "auto" */
goto out;
}
!= 0) {
goto out;
}
&derrp);
if (status == RCE_SERVER_OBJECT) {
"failed Datalink_setProperties"
"(%s, lower-link): %s",
}
}
}
out:
return (error);
}
int
{
int err = 0;
&linkmgr, 0);
return (EINVAL);
&derrp);
err = -1;
if (status == RCE_SERVER_OBJECT) {
"failed DatalinkManager_deleteVNIC(%s): %s",
}
}
return (err);
}
int
{
&linkmgr, 0);
return (ENOTSUP);
if (status == RCE_SERVER_OBJECT) {
"failed DatalinkManager_createEtherstub(%s): %s",
}
}
int
{
&linkmgr, 0);
return (ENOTSUP);
&derrp);
if (status == RCE_SERVER_OBJECT) {
"failed DatalinkManager_deleteEtherstub(%s): %s",
}
}
static int
{
goto done;
}
done:
return (err);
}
static int
{
int af;
} else {
return (EINVAL);
}
IN6_INADDR_TO_V4MAPPED(&v4addr, f);
} else {
*f = v6addr;
}
return (0);
}
static int
{
int err = 0;
&flist);
return (EINVAL);
"linkname", &dlval);
goto out;
}
out:
return (err);
}
static void
{
buf[0] = '\0';
rbuf[0] = '\0';
if (!eth_addr_is_zero(f) || !eth_addr_is_zero(m)) {
}
}
}
}
static void
{
buf[0] = '\0';
rbuf[0] = '\0';
}
}
static int
uint32cmp(const void *a, const void *b)
{
}
static int
int *range_cnt)
{
return (ENOMEM);
for (i = 0; i < nofports; i++)
if (nofports > 1)
for (i = 1; i < nofports; i++) {
} else {
}
}
return (0);
}
static int
int nofports)
{
if (nofports == 0)
return (0);
if (ofports_range == NULL)
return (ENOMEM);
if (err != 0) {
return (err);
}
FP_MULTI_ACTION_DELIM_STR) >= sizeof (buf)) {
goto no_buffer;
}
goto no_buffer;
for (i = 0; i < range_cnt; i++) {
goto no_buffer;
}
} else {
(i == 0) ? FP_NAME_VAL_DELIM :
goto no_buffer;
}
}
goto no_buffer;
}
return (0);
return (ENOBUFS);
}
static int
{
return (EINVAL);
}
return (EINVAL);
}
}
return (0);
}
static int
{
return (EINVAL);
}
return (0);
}
static int
{
return (EINVAL);
}
return (0);
}
static int
{
unsigned long long f_ulval = f;
unsigned long long m_ulval = m;
return (EINVAL);
}
return (EINVAL);
}
return (0);
}
static int
{
int err = 0;
dstr[0] = '\0';
if (err != 0)
goto out;
}
if (is_arp) {
if (err != 0)
goto out;
}
sizeof (rbuf));
if (err != 0)
goto out;
}
sizeof (rbuf));
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
} else {
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
sizeof (dstr));
if (err != 0)
goto out;
}
if (f->nw_proto != IPPROTO_ICMP &&
f->nw_proto != IPPROTO_ICMPV6) {
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
} else {
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
}
}
sizeof (rbuf));
if (err != 0)
goto out;
}
sizeof (rbuf));
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
/*
* when "f" is filled in by the parse_vlan() function, VLAN_CFI bit is
* set blindly. Unset this bit now since we don't set this bit in
* Solaris for VLAN packets.
*/
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
if (err != 0)
goto out;
}
if (err != 0)
goto out;
}
if (err != 0)
goto out;
if (err != 0)
goto out;
if (err != 0)
goto out;
}
out:
return (err);
}
static int
{
goto done;
goto done;
}
/* min-rate and priority not currently used */
goto done;
errno = 0;
goto done;
done:
return (err);
}
static int
const struct ovs_key_ethernet *ek)
{
"%sset-ether%cether_src%c%s%cether_dst%c%s",
err = 0;
}
return (err);
}
static int
const struct ovs_key_ipv4 *ipv4)
{
char *cp;
FP_ACTION_MULTI_VAL_DELIM) >= sizeof (buf))
return (ENOBUFS);
"%sdst%c%s%cprotocol%c%s%ctos%c0x%x%choplimit%c%d",
return (ENOBUFS);
return (ENOBUFS);
return (0);
}
static int
const struct ovs_key_ipv6 *ipv6)
{
sizeof (buf))
return (ENOBUFS);
"%sdst%c%s%clabel%c0x%x%cprotocol%c%s%ctos%c0x%x%choplimit%c%d",
return (ENOBUFS);
return (ENOBUFS);
return (0);
}
static int
{
return (ENOBUFS);
return (ENOBUFS);
return (0);
}
static int
{
char *cp;
FP_ACTION_MULTI_VAL_DELIM) >= sizeof (buf))
return (ENOBUFS);
return (ENOBUFS);
return (ENOBUFS);
return (0);
}
static int
{
const struct nlattr *a;
unsigned int left;
dstr[0] = '\0';
str[0] = '\0';
sizeof (dstr));
if (err != 0)
goto out;
/* if actions_len == 0, then the action is drop */
if (actions_len == 0)
goto out;
type = nl_attr_type(a);
if ((type != OVS_ACTION_ATTR_OUTPUT) ||
(lasttype != OVS_ACTION_ATTR_OUTPUT)) {
if (lasttype == OVS_ACTION_ATTR_OUTPUT) {
if (err != 0)
goto out;
(void) solaris_maxbw_action_to_DLVal(prop,
sizeof (dstr));
}
nofports = 0;
}
switch ((enum ovs_action_attr) type) {
/* These only make sense in the context of a datapath. */
case OVS_ACTION_ATTR_OUTPUT:
break;
}
break;
case OVS_ACTION_ATTR_USERSPACE: {
userdata_len > sizeof (cookie)) {
"unexpected action size %"PRIuSIZE,
break;
}
err = EOPNOTSUPP;
"type unsupported %d", userdata_len,
break;
}
break;
sizeof (buf)) {
break;
}
break;
}
break;
}
case OVS_ACTION_ATTR_SET: {
switch (nl_attr_type(aset)) {
case OVS_KEY_ATTR_PRIORITY:
break;
case OVS_KEY_ATTR_ETHERNET: {
sizeof (struct ovs_key_ethernet));
break;
}
case OVS_KEY_ATTR_IPV4: {
sizeof (struct ovs_key_ipv4));
break;
}
case OVS_KEY_ATTR_IPV6: {
sizeof (struct ovs_key_ipv6));
break;
}
case OVS_KEY_ATTR_TCP: {
sizeof (struct ovs_key_tcp));
break;
}
case OVS_KEY_ATTR_UDP: {
sizeof (struct ovs_key_udp));
break;
}
case OVS_KEY_ATTR_SCTP: {
sizeof (struct ovs_key_sctp));
break;
}
case OVS_KEY_ATTR_TUNNEL: {
break;
}
default:
err = EOPNOTSUPP;
"%d not supported",
nl_attr_type(nl_attr_get(a)));
}
break;
}
case OVS_ACTION_ATTR_PUSH_VLAN: {
vlan = nl_attr_get_unspec(a,
sizeof (struct ovs_action_push_vlan));
sizeof (buf)) {
break;
}
break;
}
break;
}
case OVS_ACTION_ATTR_POP_VLAN:
break;
}
break;
}
break;
case OVS_ACTION_ATTR_RECIRC:
case OVS_ACTION_ATTR_HASH:
case OVS_ACTION_ATTR_POP_MPLS:
case OVS_ACTION_ATTR_SAMPLE:
/* TBD */
err = EOPNOTSUPP;
"not supported", type);
case OVS_ACTION_ATTR_UNSPEC:
case __OVS_ACTION_ATTR_MAX:
}
if (err != 0)
goto out;
}
if (type == OVS_ACTION_ATTR_OUTPUT) {
dpif_log(0, "solaris_nlattr_to_DLVal outports total %d ports",
nofports);
if (err != 0)
goto out;
}
sizeof (dstr));
out:
return (err);
}
int
{
int err = 0;
"name", linkname);
goto out;
}
goto out;
}
goto out;
}
goto out;
}
if (err != 0)
goto out;
actions_len, prop);
if (err != 0)
goto out;
err = -1;
if (status == RCE_SERVER_OBJECT) {
"failed Datalink_addFlow(%s, %s): %s",
}
}
out:
return (err);
}
int
{
int err;
"name", flowname);
goto out;
}
goto out;
}
actions_len, prop);
if (err != 0)
goto out;
err = -1;
if (status == RCE_SERVER_OBJECT) {
"failed Flow_setProperties(%s): %s",
}
}
out:
return (err);
}
int
{
int error = 0;
"name", linkname);
goto out;
}
goto out;
}
goto out;
}
error = -1;
if (status == RCE_SERVER_OBJECT) {
}
}
out:
return (error);
}
static rc_err_t
{
if (err != 0)
goto out;
} else {
}
} else {
} else {
}
}
if (err != 0)
goto out;
goto out;
else
}
out:
if (err != 0)
}
static int
{
bzero(f, sizeof (*f));
bzero(m, sizeof (*m));
&flist);
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (EINVAL);
return (0);
}
int
{
int err = 0;
"name", flowname);
return (ENODEV);
}
err = -1;
if (status == RCE_SERVER_OBJECT) {
/*
* XXX For now, log DDLSTATUS_NOT_FOUND as debug until
* we can determine how to handle the RAD caching
* issue.
*/
"failed Flow_getInfo(%s): %s",
}
}
if (err == 0) {
}
return (err);
}
static int
{
/* TBD */
return (0);
}
void
{
}
static int
{
return (0);
}
static int
{
int64_t n;
errno = 0;
return (EINVAL);
return (0);
}
static int
{
return (0);
}
static int
{
int etheraddrlen;
char *sep;
uint_t i;
int err = 0;
/*
* The property value is in the format of "ether_src-xxx"
* "ether_dst-xxx"
*/
for (i = 0; i < nval; i++) {
goto out;
}
*sep = '\0';
sep++;
goto out;
}
/* Only ethernet address is supported */
if (etheraddrlen != ETHERADDRL) {
goto out;
}
if (src_set) {
} else {
}
if (dst_set) {
} else {
}
} else {
}
if (err != 0)
goto out;
}
goto out;
}
sizeof (eth_key));
out:
return (err);
}
static int
{
/*
* The property value is in the format of "src:xxx" "dst:xxx"
* "protocol:xxx" "tos:xxx" "hoplimit:xxx"
*/
for (i = 0; i < nval; i++) {
goto out;
}
*sep = '\0';
sep++;
goto out;
goto out;
goto out;
goto out;
if (ipv4.ipv4_proto != 0)
goto out;
if (protocol == 0)
goto out;
if (tos_set)
goto out;
errno = 0;
goto out;
goto out;
errno = 0;
*endp != '\0')
goto out;
}
}
err = 0;
out:
return (err);
}
static int
{
/*
* The property value is in the format of "src:xxx" "dst:xxx"
* "label:0xxxxx" "protocol:xxx" "tos:xxx" "hoplimit:xxx"
*/
for (i = 0; i < nval; i++) {
goto out;
*sep = '\0';
sep++;
sizeof (struct in6_addr));
if (!IN6_IS_ADDR_UNSPECIFIED(&in6))
goto out;
goto out;
sizeof (struct in6_addr));
if (!IN6_IS_ADDR_UNSPECIFIED(&in6))
goto out;
goto out;
if (ipv6.ipv6_proto != 0)
goto out;
if (protocol == 0)
goto out;
if (tos_set)
goto out;
errno = 0;
goto out;
if (ipv6.ipv6_hlimit != 0)
goto out;
errno = 0;
*endp != '\0') {
goto out;
}
if (ipv6.ipv6_label != 0)
goto out;
errno = 0;
goto out;
}
}
}
err = 0;
out:
return (err);
}
static int
{
/* The property value is in the format of "sport-xxx" "dport-xxx" */
for (i = 0; i < nval; i++) {
goto out;
*sep = '\0';
sep++;
if (sport != 0)
goto out;
errno = 0;
*endp != '\0') {
goto out;
}
if (dport != 0)
return (DLADM_STATUS_DUPLICATE_ARG);
errno = 0;
*endp != '\0') {
goto out;
}
}
}
err = 0;
out:
return (err);
}
static int
{
int err;
if (err != 0)
return (err);
return (0);
}
static int
{
int err;
if (err != 0)
return (err);
return (0);
}
static int
{
int err;
if (err != 0)
return (err);
return (0);
}
static int
{
void *ptr;
return (EINVAL);
/* Check if hostname resolves to multiple addresses */
ai->ai_addrlen) != 0) {
/* maps to more than one address */
return (EINVAL);
}
}
return (EINVAL);
}
return (0);
}
static int
{
int err = 0;
/*
* The property value is in the format of "src:xxx" "dst:xxx"
* "tun_id:0x%x" "tos:0x%x" "hoplimit:xxx"
*/
for (i = 0; i < nval; i++) {
return (EINVAL);
*sep = '\0';
sep++;
if (id_set)
return (EINVAL);
errno = 0;
return (EINVAL);
if (src_set)
return (EINVAL);
if (err != 0)
return (err);
if (dst_set)
return (EINVAL);
if (err != 0)
return (err);
if (tos_set)
return (EINVAL);
errno = 0;
return (EINVAL);
if (ttl_set)
return (EINVAL);
errno = 0;
*endp != '\0') {
return (EINVAL);
}
}
}
return (0);
}
static int
{
char *curr;
char c;
c = val[i];
match = (c == FP_ACTION_MULTI_VAL_DELIM ||
c == FP_ACTION_PORT_RANGE_DELIM);
continue;
if (match)
val[i] = '\0';
if (c == FP_ACTION_PORT_RANGE_DELIM) {
continue;
}
}
}
if (j >= maxcnt)
*valcntp = j;
for (i = 0; i < j; i++)
outports[i]);
return (0);
}
static int
{
char c;
if ((c = val[i]) != FP_ACTION_MULTI_VAL_DELIM &&
i != len -1)
continue;
if (c == FP_ACTION_MULTI_VAL_DELIM)
val[i] = '\0';
return (EINVAL);
}
}
if (j >= maxcnt)
*valcntp = j;
for (i = 0; i < j; i++)
propvals[i]);
return (0);
}
static int
{
for (i = 0; i < DLADM_PROP_VAL_MAX; i++) {
i * DLADM_PROP_VAL_MAX;
}
sizeof (ofaction_str)) {
goto done;
}
curr = ofaction_str;
for (i = 0; i < len; i++) {
c = ofaction_str[i];
continue;
if (match) {
ofaction_str[i] = '\0';
if (*curr == '\0') {
goto done;
}
}
if (c == FP_NAME_VAL_DELIM) {
continue;
}
goto done;
}
} else {
}
if (err != 0)
goto done;
for (j = 0; j < nval; j++)
outports[j]);
action);
else
if (err != 0)
goto done;
}
done:
return (err);
}
/* valcnt must be 1 */
static rc_err_t
void *arg)
{
case DDLVT_STRING:
goto out;
goto out;
valcnt = 1;
sizeof (propval))
goto out;
break;
case DDLVT_STRINGS:
if (val->ddlv_slist_count == 0)
goto out;
goto out;
sizeof (propval))
goto out;
break;
case DDLVT_ULONG:
goto out;
valcnt = 1;
*val->ddlv_ulval);
break;
case DDLVT_BOOLEAN:
case DDLVT_BOOLEANS:
case DDLVT_LONG:
case DDLVT_LONGS:
case DDLVT_ULONGS:
case DDLVT_DICTIONARY:
case DDLVT_DICTIONARYS:
default:
goto out;
}
propval);
out:
}
static int
{
int err = 0;
&flist);
" %d", status);
return (EINVAL);
}
"failed %d", status);
}
return (err);
}
int
{
int err = 0;
"name", flowname);
return (ENODEV);
}
err = -1;
if (status == RCE_SERVER_OBJECT) {
/*
* XXX For now, log DDLSTATUS_NOT_FOUND as debug until
* we can determine how to handle the RAD caching
* issue.
*/
"failed Flow_getInfo(%s): %s",
}
}
if (err == 0) {
}
return (err);
}
static int
{
int err = 0;
err = -1;
if (status == RCE_SERVER_OBJECT) {
derrp->dde_errmsg);
}
goto out;
}
#if _TBD_
#endif
&dlval);
goto out;
}
&dlval);
goto out;
}
&dlval);
goto out;
}
&dlval);
goto out;
}
&dlval);
goto out;
}
out:
return (err);
}
int
{
int err;
"name", flowname);
goto out;
}
out:
return (err);
}
{
}
{
}
void
{
}
{
if (stat != KSTAT2_S_OK) {
(void) printf("can't get value: %s\n",
return (0);
}
return (0);
}
return (val->kstat2_integer);
}
void
{
int anamecnt = 0, i;
&anamecnt, 0);
return;
if (anamecnt == 0) {
return;
}
for (i = 0; i < anamecnt; i++) {
int ndlist = 0;
continue;
props[0] = "ofport";
fields[0] = "current";
if (rerr == RCE_SERVER_OBJECT) {
"failed Datalink_getProperties(%s, %s): %s",
}
continue;
}
"current", &dlval);
continue;
}
}
}
for (i = 0; i < anamecnt; i++)
adr_name_rele(anamearr[i]);
}
void
{
int anamecnt = 0, i;
int err = 0;
&anamecnt, 0);
return;
if (anamecnt == 0) {
return;
}
for (i = 0; i < anamecnt; i++) {
struct flow f, m;
int ndlist = 0;
NULL) {
continue;
"sys.of") == NULL) {
continue;
}
continue;
&lastused)) != 0) {
"name"), err);
goto done;
}
err = -1;
if (rerr == RCE_SERVER_OBJECT) {
/*
* XXX For now, log DDLSTATUS_NOT_FOUND as
* debug until we can determine how to handle
* the RAD caching issue.
*/
"failed Flow_getInfo(%s): %s",
derrp->dde_errmsg);
}
goto done;
}
/* See whether this flow is created over of enabled link */
if (err != 0) {
goto done;
}
goto done;
}
props[0] = "openvswitch";
fields[0] = "current";
err = -1;
if (rerr == RCE_SERVER_OBJECT) {
"failed Datalink_getProperties(%s, %s): %s",
}
goto done;
}
"current", &dlval);
goto done;
goto done;
if (err != 0) {
"name"), err);
goto done;
}
if (err != 0) {
"flowinfo2action failed for %s: %d",
goto done;
}
done:
}
for (i = 0; i < anamecnt; i++)
adr_name_rele(anamearr[i]);
}
int
{
int error;
if (status == DLADM_STATUS_NOMEM) {
} else if (status == DLADM_STATUS_DENIED) {
} else if (status == DLADM_STATUS_OK) {
error = 0;
} else if (status == DLADM_STATUS_IOERR) {
} else {
}
return (error);
}
{
}
/*
* This is a copy of dlparse_zonelinkname() function in libinetutil. libinetutil
* is not a public interface, therefore we make a copy here.
*
* Given a linkname that can be specified using a zonename prefix retrieve
* specified we set the optional linkname and set optional zone ID return
* value to ALL_ZONES.
*/
{
char *zonetoken;
char *linktoken;
char *last;
link_name[0] = '\0';
sizeof (buffer))
return (_B_FALSE);
return (_B_FALSE);
/* If there are no other strings, return given name as linkname */
if (namelen >= MAXLINKNAMELEN)
return (_B_FALSE);
return (_B_TRUE);
}
/* First token is the zonename. Check zone and link lengths */
return (_B_FALSE);
/*
* If there are more '/' separated strings in the input
* name then we return failure. We only support a single
*/
return (_B_FALSE);
return (_B_FALSE);
}
return (_B_TRUE);
}
/*
* Sets *n_cores to the total number of cores on this system, or 0 if the
* number cannot be determined.
*/
void
{
int coreid;
int i;
*n_cores = 0;
if (stat != KSTAT2_S_OK) {
"Core count may be inaccurate.",
return;
}
for (i = 0; ; i++) {
if (stat == KSTAT2_S_OK) {
if (stat != KSTAT2_S_OK) {
"kstat2_map_get failed (%s). "
"Core count may be inaccurate.",
*n_cores = 0;
break;
}
"kstat2 value error. "
"Core count may be inaccurate.");
*n_cores = 0;
break;
}
(*n_cores)++;
}
} else if (stat == KSTAT2_S_NOT_FOUND) {
/* no more cores */
break;
} else {
"failed (%s). Core count may be inaccurate.",
*n_cores = 0;
break;
}
}
}