vrrpadm.c revision df53e1a116c70dde0788e9b6aff5f893ac34473e
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * CDDL HEADER START
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The contents of this file are subject to the terms of the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Common Development and Distribution License (the "License").
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * You may not use this file except in compliance with the License.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * See the License for the specific language governing permissions
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * and limitations under the License.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * When distributing Covered Code, include this CDDL HEADER in each
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If applicable, add the following below this CDDL HEADER, with the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * fields enclosed by brackets "[]" replaced with your own identifying
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * information: Portions Copyright [yyyy] [name of copyright owner]
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * CDDL HEADER END
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Use is subject to license terms.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutypedef void cmd_func_t(int, char *[], const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic cmd_func_t do_create, do_delete, do_enable, do_disable,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutypedef struct {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "-V <vrid> -l <link> -A {inet | inet6} [-p <priority>] "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "[-i <adv_interval>] [-o <flags>] <router_name>" },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou { "disable-router", do_disable, "<router_name>" },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "[-p <priority>] [-i <adv_interval>] [-o <flags>] <router_name>" },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "[-P | -x] [-o field[,...]] [-p] [<router_name>]" }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou { 0, 0, 0, 0 }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou { 0, 0, 0, 0 }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * structures for 'dladm show-link -s' (print statistics)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * structures for 'vrrpadm show-router'
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* name, field width, index, callback */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "ADV_INTV", 9, ROUTER_ADV_INTV, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "PRV_STAT", 9, ROUTER_PRV_STAT, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "STAT_LAST", 10, ROUTER_STAT_LAST, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "P_ADV_LAST", 11, ROUTER_P_ADV_LAST, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "M_DOWN_INTV", 12, ROUTER_M_DOWN_INTV, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "PRIMARY_IP", 20, ROUTER_PRIMARY_IP, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "VIRTUAL_IPS", 40, ROUTER_VIRTUAL_IPS, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{ "VIP_CNT", 7, ROUTER_VIP_CNT, sfunc_vrrp_conf },
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t do_show_router(const char *, ofmt_handle_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int str2opt(char *opts, uint32_t *, boolean_t *, boolean_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic char *timeval_since_str(int, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void usage();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void warn(const char *, ...);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void err_exit(const char *, ...);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void opterr_exit(int, int, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("operation failed: %s", vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < sizeof (cmds) / sizeof (cmd_t); i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudo_create(int argc, char *argv[], const char *usage)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * default value
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while ((c = getopt_long(argc, argv, ":V:l:p:i:o:A:f", lopts,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (c) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf.vvc_adver_int = (uint32_t)strtol(optarg, &endp, 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((*endp) != '\0' || conf.vvc_pri < VRRP_PRI_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((*endp) != '\0' || conf.vvc_vrid < VRRP_VRID_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (conf.vvc_name)) >= sizeof (conf.vvc_name)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("Invalid router name %s", argv[optind]);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!conf.vvc_accept && conf.vvc_pri == VRRP_PRI_OWNER)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("accept_mode must be true for virtual IP owner");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrp_create(vrrp_vh, &conf)) == VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("create-router failed: %s", vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudo_delete(int argc, char *argv[], const char *use)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrp_delete(vrrp_vh, argv[1])) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("delete-router failed: %s", vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudo_enable(int argc, char *argv[], const char *use)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrp_enable(vrrp_vh, argv[1])) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("enable-router failed: %s", vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudo_disable(int argc, char *argv[], const char *use)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrp_disable(vrrp_vh, argv[1])) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("disable-router failed: %s", vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudo_modify(int argc, char *argv[], const char *use)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while ((c = getopt_long(argc, argv, ":i:p:o:", lopts, NULL)) != EOF) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (c) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf.vvc_adver_int = (uint32_t)strtol(optarg, &endp, 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((*endp) != '\0' || conf.vvc_pri < VRRP_PRI_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strlcpy(conf.vvc_name, argv[optind], sizeof (conf.vvc_name)) >=
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("invalid router name %s", argv[optind]);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((modify_mask & VRRP_CONF_ACCEPT) && !conf.vvc_accept &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("accept_mode must be true for virtual IP owner");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("modify-router failed: %s", vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * 'show-router' one VRRP router.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudo_show_router(const char *vn, ofmt_handle_t ofmt)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrp_query(vrrp_vh, vn, &vq)) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou static char *dft_fields_str =
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "NAME,VRID,LINK,AF,PRIO,ADV_INTV,MODE,STATE,VNIC";
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou static char *ext_fields_str =
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "NAME,STATE,PRV_STAT,STAT_LAST,VNIC,PRIMARY_IP,VIRTUAL_IPS";
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "NAME,PEER,P_PRIO,P_INTV,P_ADV_LAST,M_DOWN_INTV";
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If parsable output is requested, add VIP_CNT into the output
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * for extended output. It is not needed for human-readable
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * output as it is obvious from the VIRTUAL_IPS list.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "NAME,STATE,PRV_STAT,STAT_LAST,VNIC,PRIMARY_IP,VIP_CNT,"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "VIRTUAL_IPS";
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while ((c = getopt_long(argc, argv, ":Pxpo:", l_show_opts,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (c) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If parsable output is requested, add VIP_CNT into the output
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * for extended output.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((ofmt_flags & OFMT_PARSABLE) && (fields_str == ext_fields_str))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((oferr = ofmt_open(fields_str, show_print_fields, ofmt_flags,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If some fields were badly formed in human-friendly mode, we
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * emit a warning and continue. Otherwise exit immediately.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (oferr != OFMT_EBADFIELDS || (ofmt_flags & OFMT_PARSABLE)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* Show one router */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Show all routers. First set in_cnt to 0 to find out the number
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * of vrrp routers.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((in_cnt != 0) && (names = malloc(in_cnt * VRRP_NAME_MAX)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrp_list(vrrp_vh, VRRP_VRID_NONE, NULL, AF_UNSPEC,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The VRRP routers has been changed between two vrrp_list()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * calls, try again.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Each VRRP router name is separated by '\0`
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < in_cnt; i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Callback function to print fields of the configuration information.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhousfunc_vrrp_conf(ofmt_arg_t *ofmtarg, char *buf, uint_t bufsize)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%s", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%d", conf->vvc_vrid);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%s", conf->vvc_link);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%d", conf->vvc_pri);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%d", conf->vvc_adver_int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) timeval_since_str(tinfo->vt_since_last_tran, buf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%d", peer->vp_prio);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%d", peer->vp_adver_int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) timeval_since_str(tinfo->vt_since_last_adv, buf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%d", tinfo->vt_master_down_intv);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strlen(ainfo->va_vnic) == 0 ? "--" : ainfo->va_vnic);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(buf, bufsize, "%d", ainfo->va_vipcnt);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou gettext("usage: vrrpadm <sub-command> <args> ...\n"));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < sizeof (cmds) / sizeof (cmd_t); i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("option '-%c' requires a value\nusage: %s", opt,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err_exit("unrecognized option '-%c'\nusage: %s", opt,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic char *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutimeval_since_str(int mill, char *str, size_t len)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(str, len, "%4d.%03ds", sec, msec);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Parses options string. The values of the two options will be returned
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * by 'preempt' and 'accept', and the mask 'modify_mask' will be updated
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * accordingly.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Returns 0 on success, errno on failures.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Used by do_create() and do_modify().
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Note that "opts" could be modified internally in this function.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustr2opt(char *opts, uint32_t *modify_mask, boolean_t *preempt,
df53e1a116c70dde0788e9b6aff5f893ac34473eCathy Zhou enum { o_preempt = 0, o_un_preempt, o_accept, o_no_accept };
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou static char *myopts[] = {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "un_preempt",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "no_accept",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch ((opt = getsubopt(&opts, myopts, &value))) {