dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * CDDL HEADER START
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The contents of this file are subject to the terms of the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Common Development and Distribution License (the "License").
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * You may not use this file except in compliance with the License.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * or http://www.opensolaris.org/os/licensing.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * See the License for the specific language governing permissions
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * and limitations under the License.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * When distributing Covered Code, include this CDDL HEADER in each
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If applicable, add the following below this CDDL HEADER, with the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * fields enclosed by brackets "[]" replaced with your own identifying
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * information: Portions Copyright [yyyy] [name of copyright owner]
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * CDDL HEADER END
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Use is subject to license terms.
33f5ff17089e3a43e6e730bf80384c233123dbd9Milan Jurik * Copyright 2012 Milan Jurik. All rights reserved.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misratypedef enum {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra {(int)ILB_ALG_ROUNDROBIN, "roundrobin", "rr"},
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra {(int)ILB_ALG_HASH_IP_SPORT, "hash-ip-port", "hipp"},
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra {(int)ILB_ALG_HASH_IP_VIP, "hash-ip-vip", "hipv"},
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misraip2str(ilb_ip_addr_t *ip, char *buf, size_t sz, int flags)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) inet_ntop(AF_INET, (void *)&ip->ia_v4, buf, sz);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) inet_ntop(ip->ia_af, (void *)&ip->ia_v6, buf, sz);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_str_from_val(int val, ilbadm_val_type_t *types)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (v = types; v->v_type != ILBD_BAD_VAL; v++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* we return this in all cases */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_val_from_str(char *name, ilbadm_val_type_t *types)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (v = types; v->v_type != ILBD_BAD_VAL; v++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (strncasecmp(name, v->v_name, sizeof (v->v_name)) == 0 ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra strncasecmp(name, v->v_alias, sizeof (v->v_alias)) == 0)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* we return this in all cases */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_match_key(char *key, ilbadm_key_name_t *keylist)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (t_key = keylist; t_key->k_key != ILB_KEY_BAD; t_key++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * try to match:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 1) IPv4 address
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 2) IPv6 address
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 3) a hostname
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_match_onehost(const char *val, ilb_ip_addr_t *ip, addr_type_t *a_type)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) memset((void *)&hints, 0, sizeof (hints));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * if *a_type == numeric, we only want to check whether this
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * is a (valid) numeric IP address. If we do and it is NOT,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we return _ENOENT.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (getaddrinfo(val, NULL, &hints, &ai) != 0) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) memcpy(&sa, ai->ai_addr, sizeof (sa));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) memcpy(&sa, ai->ai_addr, sizeof (sa));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_servnode_t *s = (ilbadm_servnode_t *)store;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we shouldn't need to check for length here, as a name that's
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * too long won't exist in the system anyway.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) strlcpy(sn->sd_srvID, val, sizeof (sn->sd_srvID));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_expand_ipv4range(ilbadm_sgroup_t *sg, ilb_server_data_t *srv,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (ilb_cmp_ipaddr(&new_ip, ip2, NULL) < 1) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra new_ip.ia_v4 = i_next_in_addr(&new_ip.ia_v4, 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* overflow */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* underflow */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_expand_ipv6range(ilbadm_sgroup_t *sg, ilb_server_data_t *srv,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra while (ilb_cmp_ipaddr(&new_ip, ip2, NULL) < 1) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra new_ip.ia_v6 = i_next_in6_addr(&new_ip.ia_v6, 1);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we create a list node in the servergroup for every ip address
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * in the range [ip1, ip2], where we interpret the ip addresses as
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the first ip address is already stored in "sn"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_expand_iprange(ilbadm_sgroup_t *sg, ilb_server_data_t *sr,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* if ip addresses are the same, we're done */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((cmp = ilb_cmp_ipaddr(ip1, ip2, &delta)) == 0)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("starting IP address is must be less"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra " than ending ip address in ip range specification"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* if the implicit number of IPs is too large, stop */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * parse a port spec (number or by service name) and
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * return the numeric port in *host* byte order
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Upon return, *flags contains ILB_FLAGS_SRV_PORTNAME if a service name matches
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_parseport(char *port, char *proto, int *flags)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* assumption: port names start with a non-digit */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we need to convert to host byte order to be in sync with
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * numerical ports. since result needs to be compared, this
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * is preferred to returning NW byte order
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * matches one hostname or IP address and stores it in "store".
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * space must have been pre-allocated to accept data
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * "sg" != NULL only for cases where ip ranges may be coming in.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_match_hostorip(void *store, ilbadm_sgroup_t *sg, char *val,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t is_ip_range_ok = flags & OPT_IP_RANGE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t is_addr_numeric = flags & OPT_NUMERIC_ONLY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t ports_only = flags & OPT_PORTS_ONLY;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilb_rule_data_t *rd = (ilb_rule_data_t *)store;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_servnode_t *sn = (ilbadm_servnode_t *)store;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra port_pref = val - 1; /* we increment again later on */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we parse the syntax ip[-ip][:port[-port]]
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * since IPv6 addresses contain ':'s as well, they need to be
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * enclosed in "[]" to be distinct from a potential port spec.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * therefore, we need to first check whether we're dealing with
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * IPv6 addresses before we can go search for the port seperator
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * and ipv6 range could look like this: [ff::0]-[ff::255]:80
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((keyword == ILB_KEY_SERVER) && (strchr(val, ':') != NULL) &&
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (*val != '[') && ((inet_pton(AF_INET6, val, &v6nameaddr)) != 0)) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * V6 addresses must be enclosed within
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * brackets when specifying server addresses
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("port ranges not allowed"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* ports always potentially allow ranges - XXXms: check? */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (p1 == -1 || p1 == 0 || p1 > ILB_MAX_PORT) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* ranges are only allowed for numeric ports */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra " for numeric ports"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (p2 == -1 || p2 <= p1 || p2 > ILB_MAX_PORT ||
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we fill the '-' back in, but not the port seperator,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * as the \0 in its place terminates the ip address(es)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we need to handle these situations for hosts:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * a. ip address
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * b. ip address range (ip1-ip2)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * c. a hostname (may include '-' or start with a digit)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * We want to do hostname lookup only if we're quite sure that
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we actually are looking at neither a single IP address nor a
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * range of same, as this can hang if name service is not set up
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * (sth. likely in a LB environment).
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * here's how we proceed:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 1. try to match numeric only. If that succeeds, we're done.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * (getaddrinfo, which we call in i_match_onehost(), fails if
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * it encounters a '-')
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 2. search for a '-'; if we find one, try numeric match for
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * both sides. if this fails:
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 3. re-insert '-' and try for a legal hostname.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * if the RHS of '-' is an IP but LHS is not, we might
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * have a hostname of form x-y where y is just a number
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * (this seems a valid IPv4 address), so we need to
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * try a complete hostname
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* XXX: todo: save hostname for re-display for admin */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we re-insert what we overwrote, especially in the error case
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * type-agnostic helper function to return a pointer to a
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * pristine (and maybe freshly allocated) piece of storage
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * ready for something fitting "key"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_new_storep(void *store, ilbadm_key_code_t key)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * make sure everything that needs to be there is there
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("lbalg or type is unspecified"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("proxy-src is either missing"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra " or its address family does not"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra " match that of the VIP address"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* extend as necessary */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * in parameter "sz" describes size (in bytes) of mask
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misramask_to_prefixlen(const uchar_t *mask, const int sz)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * for every byte in the mask, we start with most significant
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * bit and work our way down to the least significant bit; as
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * long as we find the bit set, we add 1 to the length. the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * first unset bit we encounter terminates this process
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (i = 0; i < sz; i++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (j = 7; j >= 0; j--) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((c & tmask) == 0)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra len = mask_to_prefixlen((uchar_t *)&ip->ia_v4.s_addr,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra len = mask_to_prefixlen((uchar_t *)&ip->ia_v6.s6_addr,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra/* copied from ifconfig.c, changed to return symbolic constants */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Convert a prefix length to a mask.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Returns 1 if ok. 0 otherwise.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Assumes the mask array is zero'ed by the caller.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrain_prefixlentomask(int prefixlen, int maxlen, uchar_t *mask)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrailbadm_set_netmask(char *val, ilb_ip_addr_t *ip, int af)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("invalid pmask provided"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("invalid pmask provided (AF mismatch?)"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("cannot convert %s to a netmask"), val);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_store_val(char *val, void *store, ilbadm_key_code_t keyword)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* some types need new storage, others don't */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra default: /* do nothing */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the proxy-src keyword is only valid for full NAT topology
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the value is either a single or a range of IP addresses.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rc = i_match_hostorip(storep, sg, val, OPT_NUMERIC_ONLY |
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * we duplicate some functionality of i_match_hostorip
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * here; that function is geared to mandate '[]' for IPv6
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * addresses, which we want to relax here, so as not to
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * make i_match_hostorip even longer, we do what we need
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((close = strchr(val, (int)']')) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* re-assemble string as we found it */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (rc == ILBADM_OK && vip->ia_af != AF_INET6) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra " with IPv6 addresses"));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rd->r_algo = i_val_from_str(val, &algo_types[0]);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * CAVEAT: the use of r_vip.ia_af implies that the VIP
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * *must* be specified on the commandline *before*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * the sticky mask.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err(gettext("option '%s' requires that VIP be "
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra "specified first"), ilbadm_key_to_opt(keyword));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rc = ilbadm_set_netmask(val, &rd->r_stickymask,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rd->r_topo = i_val_from_str(val, &topo_types[0]);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) strlcpy(hc_info->hci_test, (char *)val,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * generic parsing function.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * parses "key=value[,value]" strings in "arg". keylist determines the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * list of valid keys in the LHS. keycode determines interpretation and
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * storage in store
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * XXXms: looks like "key=value[,value]" violates spec. needs a fix
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrai_parse_optstring(char *arg, void *store, ilbadm_key_name_t *keylist,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra boolean_t is_value_list = flags & OPT_VALUE_LIST;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 1. find any commas indicating and seperating current value
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * from a following value
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 2. if we're expecting a list of values (seperated by commas)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * and have already seen the assignment, then
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * get the next "value"
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 3. else (we're looking at the first element of the RHS)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 4. find the '='
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 5. match the keyword to the list we were passed in
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 6. store the value.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ilbadm_err("%s: %s", key, ilbadm_errstr(rc));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Change to ILBADM_ILBERR to avoid more err msgs. */