/*
* 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
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdlib.h>
#include <strings.h>
#include <inttypes.h>
#include <assert.h>
#include <libilb.h>
#include <libilb_impl.h>
#include <locale.h>
typedef enum {
static int
{
if (n >= 0)
return (1);
return (-1);
}
static int
{
if (n >= 0)
return (1);
return (-1);
}
/*
* since the difference between two uint64_ts can be greater than
* what a int64_t can hold, we need to cap the result at +/- INT64_MAX
* return: < 0: x < y, 0: x == y, > 0: x > y
*/
static int64_t
{
int s = -1;
if (x == y)
return (0);
/* make sure we have x < y */
if (x > y) {
uint64_t t;
s = 1;
t = x; x = y; y = t;
}
ud = y - x;
return (INT64_MAX * s);
}
static uint64_t
{
int s = -1;
if (x == y)
return (0);
/* make sure we have x < y */
if (x > y) {
uint64_t t;
s = 1;
t = x; x = y; y = t;
}
*sgn = s;
return (y - x);
}
/*
* compare ip addresses ip1 and ip2 (as unsigned integers)
* return: -1: ip1 < ip2, 0: ip1 == ip2, 1: ip1 > ip2
* input addresses are assumed to be in network byte order
* diff contains the difference between the two with the same
* sign as the comparison result;
* NOTE: since ipv6 address (difference)s can be more than a 64bit
* value can express, the difference is capped at +/- INT64_MAX
*/
static int
{
int64_t d;
} else {
}
} else {
} else {
}
}
} else {
/*
* we're facing the dilemma that 128-bit ipv6 addresses are
* larger than the largest integer type - int64_t.
* we handle this thus:
* 1. seperate high-order and low-order bits (64 each) into
* *h and *l variables (unsigned).
* 2. calculate difference for *h and *l:
* low: unsigned
* high: signed
* 3. if high-order diff == 0, we can take low-order
* diff, if necessary cap it, convert it to signed
* and be done
* 4. if high-order and low-order signs are the same, the low-
* order bits won't significantly impact high-order
* difference, so we know that we've overflowed an int64_t;
* if high-order diff is > 1, any low-order difference won't
* change the overflow.
* 5. (dh == 1 and l_sign <= 0) or (dh == -1 and l_sign > 0),
* ie, dh == +/- 2^64
* 5a. if dl < INT64_MAX, the result is still > INT64_MAX, so
* we cap again.
* 5b. dl >= INT64_MAX
* we need to express (for dh == 1):
* (2^64) + x (where x < 0).
* Since the largest number we have is
* 2^64 - 1 == UINT64_MAX
* we use
* (2^64 - 1) + x + 1
*
* for dh == -1, all we have is
* -(2^63 - 1), so to express
* -(2^64) + x,
* we first do (dl - (2^63-1)) (which is then also < 2^63),
* si we can then add that to -(2^63 - 1);
*/
int l_sign;
/* 1. */
/* 2. */
/* 3. */
if (dh == 0) {
/* 4, */
if (dh > 0)
d = INT64_MAX;
else
d = -INT64_MAX;
/* 5. */
} else {
d = INT64_MAX;
} else {
if (dh == 1)
else
}
}
}
*diff = d;
if (d == 0)
return (0);
return (sgn);
}
int
{
int res;
return (res);
}
int
{
int res;
return (res);
}
/*
* Error strings for error values returned by libilb functions
*/
const char *
{
switch (rc) {
case ILB_STATUS_OK:
case ILB_STATUS_INTERNAL:
case ILB_STATUS_EINVAL:
" man page"));
case ILB_STATUS_ENOMEM:
" for operation"));
case ILB_STATUS_ENOENT:
case ILB_STATUS_SOCKET:
case ILB_STATUS_READ:
case ILB_STATUS_WRITE:
case ILB_STATUS_TIMER:
case ILB_STATUS_INUSE:
" cannot destroy"));
case ILB_STATUS_EEXIST:
case ILB_STATUS_PERMIT:
case ILB_STATUS_CALLBACK:
case ILB_STATUS_INPROGRESS:
case ILB_STATUS_SEND:
case ILB_STATUS_ENOHCINFO:
" test type"));
case ILB_STATUS_INVAL_CMD:
case ILB_STATUS_DUP_RULE:
" exists"));
case ILB_STATUS_ENORULE:
case ILB_STATUS_MISMATCHSG:
" servergroup"));
case ILB_STATUS_MISMATCHH:
" with previous hosts in servergroup or with rule"));
case ILB_STATUS_SGUNAVAIL:
" server group"));
case ILB_STATUS_SGINUSE:
" group - its in use with other active rules"));
case ILB_STATUS_SGEXISTS:
case ILB_STATUS_SGFULL:
" add any more servers to this servergroup"));
case ILB_STATUS_SGEMPTY:
" any servers"));
case ILB_STATUS_NAMETOOLONG:
" only contain a maximum of 14 characters"));
case ILB_STATUS_CFGAUTH:
" execute command"));
case ILB_STATUS_CFGUPDATE:
" to update persistent config. Panic?"));
case ILB_STATUS_BADSG:
" does not match that of the servers' in associated"
" servergroup"));
case ILB_STATUS_INVAL_SRVR:
" servergroup, as the servergroup is associated to rule(s)"
"with the server's port"));
case ILB_STATUS_INVAL_ENBSRVR:
" because it's not associated with any rule"));
case ILB_STATUS_BADPORT:
" not match that of the servers' in"
" associated servergroup"));
case ILB_STATUS_SRVUNAVAIL:
case ILB_STATUS_RULE_NO_HC:
"check enabled"));
"health check does not match"));
default:
}
}
/* Allocate space for a specified request to be sent to ilbd. */
{
sz = sizeof (ilb_comm_t);
switch (cmd) {
case ILBD_CREATE_RULE:
sz += sizeof (ilb_rule_info_t);
break;
case ILBD_RETRIEVE_RULE:
case ILBD_DESTROY_RULE:
case ILBD_ENABLE_RULE:
case ILBD_DISABLE_RULE:
case ILBD_RETRIEVE_SG_HOSTS:
case ILBD_DESTROY_SERVERGROUP:
case ILBD_CREATE_SERVERGROUP:
case ILBD_DESTROY_HC:
case ILBD_GET_HC_INFO:
case ILBD_GET_HC_SRVS:
sz += sizeof (ilbd_name_t);
break;
case ILBD_ENABLE_SERVER:
case ILBD_DISABLE_SERVER:
case ILBD_ADD_SERVER_TO_GROUP:
case ILBD_SRV_ADDR2ID:
case ILBD_SRV_ID2ADDR:
break;
case ILBD_CREATE_HC:
sz += sizeof (ilb_hc_info_t);
break;
default:
/* Should not reach here. */
assert(0);
break;
}
return (NULL);
return (ic);
}