/*
* 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 <stdio.h>
#include <sys/ethernet.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stropts.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include <libintl.h>
#include <netdb.h>
#include <net/if_types.h>
#include <libdlflow.h>
#include <libdlflow_impl.h>
#include <libdladm_impl.h>
#include <libdllink.h>
#include <zone.h>
/* minimum buffer size for DLDIOCWALKFLOW */
/*
* Convert a diagnostic returned by the kernel to dladm_status_t
*/
static dladm_status_t
{
switch (ioc_diag) {
case FLOW_IOC_DIAG_NONE:
return (DLADM_STATUS_OK);
case FLOW_IOC_DIAG_IP_LOCAL:
return (DLADM_STATUS_FLOW_IP_LOCAL);
case FLOW_IOC_DIAG_IP_REMOTE:
return (DLADM_STATUS_FLOW_IP_REMOTE);
case FLOW_IOC_DIAG_DSFIELD:
return (DLADM_STATUS_FLOW_DSFIELD);
case FLOW_IOC_DIAG_PROTO:
return (DLADM_STATUS_FLOW_PROTO);
return (DLADM_STATUS_FLOW_PROTO_LOCAL);
return (DLADM_STATUS_FLOW_PROTO_REMOTE);
return (DLADM_STATUS_FLOW_ATTR_INVALID);
default:
return (DLADM_STATUS_FAILED);
}
}
/* Remove a flow in the DB */
static int
const char *root)
{
return (-1);
return (0);
}
static char *
{
/* add 4 byte to store '/' and the net mask */
if (localaddr)
else
} else {
if (localaddr)
else
}
if (localaddr)
prefix_max, &prefix_len);
else
prefix_max, &prefix_len);
return (ret_str);
}
/* Add flow to the DB */
static dladm_status_t
{
!= DLADM_STATUS_OK)
return (status);
/* set link name over which the flow resides */
if (status != DLADM_STATUS_OK)
goto done;
if (status != DLADM_STATUS_OK)
goto done;
}
/* flow policy */
if (status != DLADM_STATUS_OK)
goto done;
}
/* flow descriptor */
if (status != DLADM_STATUS_OK)
goto done;
if (status != DLADM_STATUS_OK)
goto done;
}
char *addr_str;
if (status != DLADM_STATUS_OK)
goto done;
}
/* add 4 byte to store '/' and the net mask */
char *addr_str;
if (status != DLADM_STATUS_OK)
goto done;
}
if (status != DLADM_STATUS_OK)
goto done;
}
if (status != DLADM_STATUS_OK)
goto done;
}
if (status != DLADM_STATUS_OK)
goto done;
}
/*
* Commit the flow configuration.
*/
done:
return (status);
}
/* Add flow to kernel */
{
int rc;
/* create flow */
sizeof (mac_resource_props_t));
}
if (rc < 0)
if (status != DLADM_STATUS_OK) {
}
return (status);
}
/* Remove flow from kernel */
{
return (status);
}
{
return (status);
}
/* ARGSUSED */
{
/* Extract flow attributes from attrlist */
&flowdesc)) != DLADM_STATUS_OK)
return (status);
/* Extract resource_ctl and cpu_list from proplist */
&mrp)) != DLADM_STATUS_OK)
return (status);
/* Add flow in kernel */
return (status);
/* Add flow to DB */
sizeof (db_attr.fi_flowname));
!= DLADM_STATUS_OK) {
/* if write to DB failed, remove flow from kernel */
return (status);
}
done:
return (status);
}
/*
* Remove a flow.
*/
/* ARGSUSED */
const char *root)
{
/*
* Check if this zone owns this flow or not. Flows can only be removed
* by the owner zone or the global zone.
*/
return (DLADM_STATUS_FLOW_WRONG_ZONE);
/* Before remove, check if the flow is onloan to another zone */
return (DLADM_STATUS_FLOW_WRONG_ZONE);
/* Remove flow from kernel */
if (tempop)
return (status);
/* Remove flow from DB */
if (!tempop) {
/* flow DB */
s = dladm_errno2status(errno);
}
done:
if (!tempop) {
if (s == DLADM_STATUS_OK) {
if (status == DLADM_STATUS_NOTFOUND)
status = s;
} else {
if (s != DLADM_STATUS_NOTFOUND)
status = s;
}
}
return (status);
}
/*
* Get an existing flow in the DB.
*/
typedef struct get_db_state {
void *gs_arg;
/*
* Walk through the flows defined on the system and for each flow
* invoke <fn>(<arg>, <flow>);
* Currently used for show-flow and set-linkprop -p zone.
*/
/* ARGSUSED */
{
int i, bufsize;
ssize_t s;
return (DLADM_STATUS_BADARG);
if (persist) {
if (cur_zoneid == GLOBAL_ZONEID)
return (DLADM_STATUS_ZONE_ERR);
/*
* Global zone needs to walks through all zones, if the
* zone that has been walked is not activate, go to
* the next one.
*/
if (s < 0 && cur_zoneid == GLOBAL_ZONEID) {
break;
continue;
}
if (status != DLADM_STATUS_OK &&
return (status);
if (status == DLADM_STATUS_OK) {
/*
* Check if flow's underlying link is still
* present as gz may re-assign the link to
* another zone
*/
if (status == DLADM_STATUS_NOTFOUND)
}
continue;
} else if (status == DLADM_STATUS_NOTFOUND &&
cur_zoneid == GLOBAL_ZONEID) {
break;
continue;
}
if (next_zid != cur_zoneid) {
} else {
&onloan);
if (status != DLADM_STATUS_OK)
continue;
else
sizeof (attr.fa_flowname));
}
sizeof (attr.fa_flow_desc));
sizeof (attr.fa_resource_props));
break;
}
} else {
return (status);
}
bufsize *= 2;
continue;
}
}
goto bail;
}
&onloan);
if (zid != cur_zoneid) {
ssize_t s = 0;
if (zid == GLOBAL_ZONEID)
else
if (!onloan && s < 0)
continue;
} else {
sizeof (attr.fa_flowname));
}
sizeof (attr.fa_flow_desc));
sizeof (attr.fa_resource_props));
break;
}
}
bail:
return (status);
}
{
int ret_err = 0;
while (ret_err == 0) {
&ret_err);
if (status != DLADM_STATUS_OK) {
return (status == DLADM_STATUS_NOTFOUND ?
}
return (DLADM_STATUS_OK);
/*
* Flows can exist for removed links. In such cases,
* i_dladm_flow_add() will return DLADM_STATUS_NOTFOUND.
* Ensure that such failures do not prevent other flows from
* being added.
*/
if (status != DLADM_STATUS_OK)
return (status);
}
return (status);
}
void
{
int ret_err = 0;
while (ret_err == 0) {
&ret_err);
if (status != DLADM_STATUS_OK)
break;
break;
zoneid);
}
}
{
return (DLADM_STATUS_BADARG);
while (prefixlen > 0) {
if (prefixlen >= 8) {
*mask++ = 0xFF;
prefixlen -= 8;
continue;
}
prefixlen--;
}
return (DLADM_STATUS_OK);
}
{
int bits;
int i, end;
switch (plen) {
case IP_ABITS:
end = 3;
break;
case IPV6_ABITS:
end = 0;
break;
default:
return (DLADM_STATUS_BADARG);
}
for (i = 3; i >= end; i--) {
plen -= 32;
continue;
}
if (bits == 0)
break;
}
return (DLADM_STATUS_OK);
}