1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * CDDL HEADER START
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
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 *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * or http://www.opensolaris.org/os/licensing.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * See the License for the specific language governing permissions
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * and limitations under the License.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
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 *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * CDDL HEADER END
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich/*
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich * Copyright (c) 2012, Joyent, Inc. All rights reserved.
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich */
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <sys/types.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <sys/socket.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <sys/sockio.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <sys/sysevent/vrrp.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <sys/sysevent/eventdefs.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <sys/varargs.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <auth_attr.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <ctype.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <fcntl.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <stdlib.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <strings.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <errno.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <unistd.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <zone.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <libsysevent.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <limits.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <locale.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <arpa/inet.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <signal.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <assert.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <ucred.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <bsm/adt.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <bsm/adt_event.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <priv_utils.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <libdllink.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <libdlvnic.h>
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey#include <libipadm.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <pwd.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <libvrrpadm.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include <net/route.h>
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#include "vrrpd_impl.h"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * A VRRP router can be only start participating the VRRP protocol of a virtual
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * router when all the following conditions are met:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - The VRRP router is enabled (vr->vvr_conf.vvc_enabled is _B_TRUE)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - The RX socket is successfully created over the physical interface to
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * receive the VRRP multicast advertisement. Note that one RX socket can
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * be shared by several VRRP routers configured over the same physical
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface. (See vrrpd_init_rxsock())
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - The TX socket is successfully created over the VNIC interface to send
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the VRRP advertisment. (See vrrpd_init_txsock())
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - The primary IP address has been successfully selected over the physical
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface. (See vrrpd_select_primary())
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If a VRRP router is enabled but the other conditions haven't be satisfied,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the router will be stay at the VRRP_STATE_INIT state. If all the above
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * conditions are met, the VRRP router will be transit to either
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the VRRP_STATE_MASTER or the VRRP_STATE_BACKUP state, depends on the VRRP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * protocol.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define skip_whitespace(p) while (isspace(*(p))) ++(p)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define BUFFSIZE 65536
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define VRRPCONF "/etc/inet/vrrp.conf"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutypedef struct vrrpd_rtsock_s {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int vrt_af; /* address family */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int vrt_fd; /* socket for the PF_ROUTE msg */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iu_event_id_t vrt_eid; /* event ID */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou} vrrpd_rtsock_t;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic ipadm_handle_t vrrp_ipadm_handle = NULL; /* libipadm handle */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_logflag = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouboolean_t vrrp_debug_level = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouiu_eh_t *vrrpd_eh = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouiu_tq_t *vrrpd_timerq = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_handle_t vrrpd_vh = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrpd_cmdsock_fd = -1; /* socket to communicate */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* between vrrpd/libvrrpadm */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic iu_event_id_t vrrpd_cmdsock_eid = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrpd_ctlsock_fd = -1; /* socket to bring up/down */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* the virtual IP addresses */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrpd_ctlsock6_fd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrpd_rtsock_t vrrpd_rtsocks[2] = {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {AF_INET, -1, -1},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {AF_INET6, -1, -1}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou};
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic iu_timer_id_t vrrp_scan_timer_id = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy ZhouTAILQ_HEAD(vrrp_vr_list_s, vrrp_vr_s);
1cb875ae88fb9463b368e725c2444776595895cbCathy ZhouTAILQ_HEAD(vrrp_intf_list_s, vrrp_intf_s);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic struct vrrp_vr_list_s vrrp_vr_list;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic struct vrrp_intf_list_s vrrp_intf_list;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic char vrrpd_conffile[MAXPATHLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Multicast address of VRRP advertisement in network byte order
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_addr_t vrrp_muladdr4;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_addr_t vrrp_muladdr6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrpd_scan_interval = 20000; /* ms */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhoustatic int pfds[2];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * macros to calculate skew_time and master_down_timer
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Note that the input is in centisecs and output are in msecs
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define SKEW_TIME(pri, intv) ((intv) * (256 - (pri)) / 256)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define MASTER_DOWN_INTERVAL(pri, intv) (3 * (intv) + SKEW_TIME((pri), (intv)))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define SKEW_TIME_VR(vr) \
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou SKEW_TIME((vr)->vvr_conf.vvc_pri, (vr)->vvr_master_adver_int)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define MASTER_DOWN_INTERVAL_VR(vr) \
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou MASTER_DOWN_INTERVAL((vr)->vvr_conf.vvc_pri, (vr)->vvr_master_adver_int)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define VRRP_CONF_UPDATE 0x01
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define VRRP_CONF_DELETE 0x02
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic char *af_str(int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic iu_tq_callback_t vrrp_adv_timeout;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic iu_tq_callback_t vrrp_b2m_timeout;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic iu_eh_callback_t vrrpd_sock_handler;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic iu_eh_callback_t vrrpd_rtsock_handler;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic iu_eh_callback_t vrrpd_cmdsock_handler;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int daemon_init();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_init();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_fini();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_cmdsock_create();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmdsock_destroy();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_rtsock_create();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_rtsock_destroy();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_ctlsock_create();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_ctlsock_destroy();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_scan_timer(iu_tq_t *, void *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_scan(int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_init_rxsock(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_fini_rxsock(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_init_txsock(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_init_txsock_v4(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_init_txsock_v6(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_fini_txsock(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_create_vr(vrrp_vr_conf_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_enable_vr(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_disable_vr(vrrp_vr_t *, vrrp_intf_t *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_delete_vr(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_create(vrrp_vr_conf_t *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_delete(const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_enable(const char *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_disable(const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_modify(vrrp_vr_conf_t *, uint32_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_list(vrid_t, char *, int, vrrp_ret_list_t *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_query(const char *, vrrp_ret_query_t *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_name(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_vrid(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_af(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_pri(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_adver_int(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_preempt(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_accept(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_ifname(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t vrrp_rd_prop_enabled(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_name(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_vrid(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_af(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_pri(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_adver_int(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_preempt(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_accept(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_ifname(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrp_wt_prop_enabled(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmd_create(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmd_delete(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmd_enable(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmd_disable(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmd_modify(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmd_list(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cmd_query(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_vr_t *vrrpd_lookup_vr_by_vrid(char *, vrid_t vrid_t, int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_vr_t *vrrpd_lookup_vr_by_name(const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_intf_t *vrrpd_lookup_if(const char *, int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_create_if(const char *, int, uint32_t, vrrp_intf_t **);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_delete_if(vrrp_intf_t *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_create_ip(vrrp_intf_t *, const char *, vrrp_addr_t *,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t flags);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_delete_ip(vrrp_intf_t *, vrrp_ip_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_init_ipcache(int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_update_ipcache(int);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic ipadm_status_t vrrpd_walk_addr_info(int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_add_ipaddr(char *, int, vrrp_addr_t *,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int, uint64_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_ip_t *vrrpd_select_primary(vrrp_intf_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_reselect_primary(vrrp_intf_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_reenable_all_vr();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_remove_if(vrrp_intf_t *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic uint16_t in_cksum(int, uint16_t, void *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic uint16_t vrrp_cksum4(struct in_addr *, struct in_addr *,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t, vrrp_pkt_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic uint16_t vrrp_cksum6(struct in6_addr *, struct in6_addr *,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t, vrrp_pkt_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic size_t vrrpd_build_vrrp(vrrp_vr_t *, uchar_t *, int, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_process_adv(vrrp_vr_t *, vrrp_addr_t *, vrrp_pkt_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_send_adv(vrrp_vr_t *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* state transition functions */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_state_i2m(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_state_i2b(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_state_m2i(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_state_b2i(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_state_b2m(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_state_m2b(vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_state_trans(vrrp_state_t, vrrp_state_t, vrrp_vr_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_set_noaccept(vrrp_vr_t *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_virtualip_update(vrrp_vr_t *, boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_virtualip_updateone(vrrp_intf_t *, vrrp_ip_t *,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int vrrpd_post_event(const char *, vrrp_state_t, vrrp_state_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_initconf();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_updateconf(vrrp_vr_conf_t *, uint_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_write_vrconf(char *, size_t, vrrp_vr_conf_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_read_vrconf(char *, vrrp_vr_conf_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t vrrpd_readprop(const char *, vrrp_vr_conf_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrpd_cleanup();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void vrrp_log(int, char *, ...);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int timeval_to_milli(struct timeval);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic struct timeval timeval_delta(struct timeval, struct timeval);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutypedef struct vrrpd_prop_s {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char *vs_propname;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t (*vs_propread)(vrrp_vr_conf_t *, const char *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int (*vs_propwrite)(vrrp_vr_conf_t *, char *, size_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou} vrrp_prop_t;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * persistent VRRP properties array
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_prop_t vrrp_prop_info_tbl[] = {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"name", vrrp_rd_prop_name, vrrp_wt_prop_name},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"vrid", vrrp_rd_prop_vrid, vrrp_wt_prop_vrid},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"priority", vrrp_rd_prop_pri, vrrp_wt_prop_pri},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"adv_intval", vrrp_rd_prop_adver_int, vrrp_wt_prop_adver_int},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"preempt_mode", vrrp_rd_prop_preempt, vrrp_wt_prop_preempt},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"accept_mode", vrrp_rd_prop_accept, vrrp_wt_prop_accept},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"interface", vrrp_rd_prop_ifname, vrrp_wt_prop_ifname},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"af", vrrp_rd_prop_af, vrrp_wt_prop_af},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {"enabled", vrrp_rd_prop_enabled, vrrp_wt_prop_enabled}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou};
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define VRRP_PROP_INFO_TABSIZE \
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (sizeof (vrrp_prop_info_tbl) / sizeof (vrrp_prop_t))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutypedef void vrrp_cmd_func_t(void *, void *, size_t *);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutypedef struct vrrp_cmd_info_s {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_type_t vi_cmd;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t vi_reqsize;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t vi_acksize; /* 0 if the size is variable */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t vi_setop; /* Set operation? Check credentials */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_func_t *vi_cmdfunc;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou} vrrp_cmd_info_t;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_cmd_info_t vrrp_cmd_info_tbl[] = {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {VRRP_CMD_CREATE, sizeof (vrrp_cmd_create_t),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vrrp_ret_create_t), _B_TRUE, vrrpd_cmd_create},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {VRRP_CMD_DELETE, sizeof (vrrp_cmd_delete_t),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vrrp_ret_delete_t), _B_TRUE, vrrpd_cmd_delete},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {VRRP_CMD_ENABLE, sizeof (vrrp_cmd_enable_t),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vrrp_ret_enable_t), _B_TRUE, vrrpd_cmd_enable},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {VRRP_CMD_DISABLE, sizeof (vrrp_cmd_disable_t),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vrrp_ret_disable_t), _B_TRUE, vrrpd_cmd_disable},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {VRRP_CMD_MODIFY, sizeof (vrrp_cmd_modify_t),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vrrp_ret_modify_t), _B_TRUE, vrrpd_cmd_modify},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {VRRP_CMD_QUERY, sizeof (vrrp_cmd_query_t), 0,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou _B_FALSE, vrrpd_cmd_query},
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou {VRRP_CMD_LIST, sizeof (vrrp_cmd_list_t), 0,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou _B_FALSE, vrrpd_cmd_list}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou};
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou#define VRRP_DOOR_INFO_TABLE_SIZE \
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (sizeof (vrrp_cmd_info_tbl) / sizeof (vrrp_cmd_info_t))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouipaddr_cmp(int af, vrrp_addr_t *addr1, vrrp_addr_t *addr2)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (af == AF_INET) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (memcmp(&addr1->in4.sin_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &addr2->in4.sin_addr, sizeof (struct in_addr)));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (memcmp(&addr1->in6.sin6_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &addr2->in6.sin6_addr, sizeof (struct in6_addr)));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_vr_t *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_lookup_vr_by_vrid(char *ifname, vrid_t vrid, int af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcmp(vr->vvr_conf.vvc_link, ifname) == 0 &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_vrid == vrid &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_af == af) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_vr_t *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_lookup_vr_by_name(const char *name)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcmp(vr->vvr_conf.vvc_name, name) == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_intf_t *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_lookup_if(const char *ifname, int af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *intf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(intf, &vrrp_intf_list, vvi_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcmp(ifname, intf->vvi_ifname) == 0 &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou af == intf->vvi_af) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (intf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_create_if(const char *ifname, int af, uint32_t ifindex,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t **intfp)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *intf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_create_if(%s, %s, %d)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ifname, af_str(af), ifindex);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (((*intfp) = malloc(sizeof (vrrp_intf_t))) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_create_if(): failed to "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "allocate %s/%s interface", ifname, af_str(af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOMEM);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf = *intfp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_INIT(&intf->vvi_iplist);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(intf->vvi_ifname, ifname, sizeof (intf->vvi_ifname));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_af = af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_sockfd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_nvr = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_eid = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_pip = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifindex = ifindex;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_state = NODE_STATE_NEW;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_vr_state = VRRP_STATE_INIT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_INSERT_TAIL(&vrrp_intf_list, intf, vvi_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * An interface is deleted. If update_vr is true, the deletion of the interface
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * may cause the state transition of assoicated VRRP router (if this interface
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * is either the primary or the VNIC interface of the VRRP router); otherwise,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * simply delete the interface without updating the VRRP router.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_delete_if(vrrp_intf_t *intf, boolean_t update_vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_delete_if(%s, %s, %supdate_vr)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifname, af_str(intf->vvi_af), update_vr ? "" : "no_");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (update_vr) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If a this interface is the physical interface or the VNIC
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * of a VRRP router, the deletion of the interface (no IP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * address exists on this interface) may cause the state
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * transition of the VRRP router. call vrrpd_remove_if()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * to find all corresponding VRRP router and update their
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * states.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_remove_if(intf, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * First remove and delete all the IP addresses on the interface
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (!TAILQ_EMPTY(&intf->vvi_iplist)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip = TAILQ_FIRST(&intf->vvi_iplist);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_ip(intf, ip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Then remove and delete the interface
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_REMOVE(&vrrp_intf_list, intf, vvi_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) free(intf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_create_ip(vrrp_intf_t *intf, const char *lifname, vrrp_addr_t *addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t flags)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(intf->vvi_af, addr, abuf, INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_create_ip(%s, %s, %s, 0x%x)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifname, lifname, abuf, flags);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((ip = malloc(sizeof (vrrp_ip_t))) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_create_ip(%s, %s):"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed to allocate IP", lifname, abuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOMEM);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strncpy(ip->vip_lifname, lifname, sizeof (ip->vip_lifname));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_state = NODE_STATE_NEW;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_flags = flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&ip->vip_addr, addr, sizeof (ip->vip_addr));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Make sure link-local IPv6 IP addresses are at the head of the list
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (intf->vvi_af == AF_INET6 &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_INSERT_HEAD(&intf->vvi_iplist, ip, vip_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_INSERT_TAIL(&intf->vvi_iplist, ip, vip_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_delete_ip(vrrp_intf_t *intf, vrrp_ip_t *ip)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int af = intf->vvi_af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(af, &ip->vip_addr, abuf, sizeof (abuf), _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_delete_ip(%s, %s, %s) is %sprimary",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifname, ip->vip_lifname, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_pip == ip ? "" : "not ");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (intf->vvi_pip == ip)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_pip = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_REMOVE(&intf->vvi_iplist, ip, vip_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) free(ip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic char *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhourtm_event2str(uchar_t event)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (event) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_NEWADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_NEWADDR");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_DELADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_DELADDR");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_IFINFO:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_IFINFO");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_ADD:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_ADD");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_DELETE:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_DELETE");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_CHANGE:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_CHANGE");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_OLDADD:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_OLDADD");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_OLDDEL:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_OLDDEL");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_CHGADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_CHGADDR");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_FREEADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_FREEADDR");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou default:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("RTM_OTHER");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou/*
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * This is called by the child process to inform the parent process to
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * exit with the given return value. Note that the child process
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * (the daemon process) informs the parent process to exit when anything
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * goes wrong or when all the intialization is done.
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhoustatic int
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhouvrrpd_inform_parent_exit(int rv)
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou{
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou int err = 0;
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou /*
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * If vrrp_debug_level is none-zero, vrrpd is not running as
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * a daemon. Return directly.
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou if (vrrp_debug_level != 0)
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou return (0);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou if (write(pfds[1], &rv, sizeof (int)) != sizeof (int)) {
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou err = errno;
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) close(pfds[1]);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou return (err);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou }
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) close(pfds[1]);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou return (0);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou}
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouint
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoumain(int argc, char *argv[])
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int c, err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct sigaction sa;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sigset_t mask;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct rlimit rl;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) setlocale(LC_ALL, "");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) textdomain(TEXT_DOMAIN);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * We need PRIV_SYS_CONFIG to post VRRP sysevent, PRIV_NET_RAWACESS
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * and PRIV_NET_ICMPACCESS to open the raw socket, PRIV_SYS_IP_CONFIG
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * to bring up/down the virtual IP addresses, and PRIV_SYS_RESOURCE to
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * setrlimit().
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Note that sysevent is not supported in non-global zones.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (getzoneid() == GLOBAL_ZONEID) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = __init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou PRIV_SYS_CONFIG, PRIV_NET_RAWACCESS, PRIV_NET_ICMPACCESS,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou PRIV_SYS_IP_CONFIG, PRIV_SYS_RESOURCE, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = __init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou PRIV_NET_RAWACCESS, PRIV_NET_ICMPACCESS,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou PRIV_SYS_IP_CONFIG, PRIV_SYS_RESOURCE, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "main(): init_daemon_priv() failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (EXIT_FAILURE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If vrrpd is started by other process, it will inherit the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * signal block mask. We unblock all signals to make sure the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * signal handling will work normally.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) sigfillset(&mask);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) thr_sigsetmask(SIG_UNBLOCK, &mask, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sa.sa_handler = vrrpd_cleanup;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sa.sa_flags = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) sigemptyset(&sa.sa_mask);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) sigaction(SIGINT, &sa, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) sigaction(SIGQUIT, &sa, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) sigaction(SIGTERM, &sa, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_debug_level = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(vrrpd_conffile, VRRPCONF, sizeof (vrrpd_conffile));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while ((c = getopt(argc, argv, "d:f:")) != EOF) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (c) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case 'd':
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_debug_level = atoi(optarg);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case 'f':
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(vrrpd_conffile, optarg,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vrrpd_conffile));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou default:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou closefrom(3);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrp_debug_level == 0 && (daemon_init() != 0)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "main(): daemon_init() failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (EXIT_FAILURE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou rl.rlim_cur = RLIM_INFINITY;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou rl.rlim_max = RLIM_INFINITY;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "main(): setrlimit() failed");
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou goto child_out;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_init() != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "main(): vrrpd_init() failed");
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou goto child_out;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Get rid of unneeded privileges.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, PRIV_SYS_RESOURCE, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Read the configuration and initialize the existing VRRP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * configuration
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_initconf();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou /*
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * Inform the parent process that it can successfully exit.
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou if ((err = vrrpd_inform_parent_exit(EXIT_SUCCESS)) != 0) {
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou vrrpd_cleanup();
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou vrrp_log(VRRP_WARNING, "vrrpd_inform_parent_exit() failed: %s",
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou strerror(err));
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou return (EXIT_FAILURE);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou }
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Start the loop to handle the timer and the IO events.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (iu_handle_events(vrrpd_eh, vrrpd_timerq)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case -1:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "main(): iu_handle_events() failed "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "abnormally");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou default:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_cleanup();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (EXIT_SUCCESS);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhouchild_out:
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) vrrpd_inform_parent_exit(EXIT_FAILURE);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou return (EXIT_FAILURE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudaemon_init()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pid_t pid;
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou int rv;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "daemon_init()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (getenv("SMF_FMRI") == NULL) {
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou vrrp_log(VRRP_ERR, "daemon_init(): vrrpd is an smf(5) managed "
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou "service and should not be run from the command line.");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (-1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou /*
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * Create the pipe used for the child process to inform the parent
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * process to exit after all initialization is done.
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou if (pipe(pfds) < 0) {
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou vrrp_log(VRRP_ERR, "daemon_init(): pipe() failed: %s",
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (-1);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou if ((pid = fork()) < 0) {
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou vrrp_log(VRRP_ERR, "daemon_init(): fork() failed: %s",
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou strerror(errno));
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) close(pfds[0]);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) close(pfds[1]);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou return (-1);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou }
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou if (pid != 0) { /* Parent */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) close(pfds[1]);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou /*
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * Read the child process's return value from the pfds.
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou * If the child process exits unexpectedly, read() returns -1.
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou if (read(pfds[0], &rv, sizeof (int)) != sizeof (int)) {
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou vrrp_log(VRRP_ERR, "daemon_init(): child process "
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou "exited unexpectedly %s", strerror(errno));
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) kill(pid, SIGTERM);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou rv = EXIT_FAILURE;
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou }
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) close(pfds[0]);
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou exit(rv);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * in child process, became a daemon, and return to main() to continue.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) close(pfds[0]);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) chdir("/");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) setsid();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(2);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) open("/dev/null", O_RDWR, 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) dup2(0, 1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) dup2(0, 2);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou openlog("vrrpd", LOG_PID, LOG_DAEMON);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_logflag = 1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_init()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_init()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_INIT(&vrrp_vr_list);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_INIT(&vrrp_intf_list);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrp_open(&vrrpd_vh) != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init(): vrrp_open() failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vrrpd_timerq = iu_tq_create()) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init(): iu_tq_create() failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vrrpd_eh = iu_eh_create()) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init(): iu_eh_create() failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the AF_UNIX socket used to communicate with libvrrpadm.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * This socket is used to receive the administrative requests and
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * send back the results.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_cmdsock_create() != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init(): vrrpd_cmdsock_create() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the VRRP control socket used to bring up/down the virtual
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * IP addresses. It is also used to set the IFF_NOACCEPT flag of
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the virtual IP addresses.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_ctlsock_create() != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init(): vrrpd_ctlsock_create() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the PF_ROUTER socket used to listen to the routing socket
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * messages and build the interface/IP address list.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_rtsock_create() != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init(): vrrpd_rtsock_create() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Open the libipadm handle */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ipadm_open(&vrrp_ipadm_handle, 0) != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey vrrp_log(VRRP_ERR, "vrrpd_init(): ipadm_open() failed");
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto fail;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Build the list of interfaces and IP addresses. Also, start the time
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * to scan the interfaces/IP addresses periodically.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_scan(AF_INET);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_scan(AF_INET6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vrrp_scan_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_scan_interval, vrrpd_scan_timer, NULL)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init(): start scan_timer failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Initialize the VRRP multicast address.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bzero(&vrrp_muladdr4, sizeof (vrrp_addr_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_muladdr4.in4.sin_family = AF_INET;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) inet_pton(AF_INET, "224.0.0.18", &vrrp_muladdr4.in4.sin_addr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bzero(&vrrp_muladdr6, sizeof (vrrp_addr_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_muladdr6.in6.sin6_family = AF_INET6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) inet_pton(AF_INET6, "ff02::12", &vrrp_muladdr6.in6.sin6_addr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoufail:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_fini()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_fini()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_cancel_timer(vrrpd_timerq, vrrp_scan_timer_id, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_scan_timer_id = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_rtsock_destroy();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_ctlsock_destroy();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_cmdsock_destroy();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_eh != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iu_eh_destroy(vrrpd_eh);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_eh = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_timerq != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iu_tq_destroy(vrrpd_timerq);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_timerq = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_close(vrrpd_vh);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_vh = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(TAILQ_EMPTY(&vrrp_vr_list));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(TAILQ_EMPTY(&vrrp_intf_list));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_close(vrrp_ipadm_handle);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cleanup(void)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *intf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_cleanup()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (!TAILQ_EMPTY(&vrrp_vr_list)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr = TAILQ_FIRST(&vrrp_vr_list);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_vr(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (!TAILQ_EMPTY(&vrrp_intf_list)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf = TAILQ_FIRST(&vrrp_intf_list);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_if(intf, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou closelog();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou exit(1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Read the configuration file and initialize all the existing VRRP routers.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_initconf()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou FILE *fp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char line[LINE_MAX];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int linenum = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_conf_t conf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_initconf()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((fp = fopen(vrrpd_conffile, "rF")) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "failed to open the configuration file %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_conffile);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (fgets(line, sizeof (line), fp) != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou linenum++;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf.vvc_vrid = VRRP_VRID_NONE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_read_vrconf(line, &conf)) != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "failed to parse %d line %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou linenum, line);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Blank or comment line
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (conf.vvc_vrid == VRRP_VRID_NONE)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * No need to update the configuration since the VRRP router
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * created/enabled based on the existing configuration.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_create(&conf, _B_FALSE)) != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "VRRP router %s creation failed: "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%s", conf.vvc_name, vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (conf.vvc_enabled &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ((err = vrrpd_enable(conf.vvc_name, _B_FALSE)) !=
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRP_SUCCESS)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "VRRP router %s enable failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf.vvc_name, vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) fclose(fp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the AF_UNIX socket used to communicate with libvrrpadm.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * This socket is used to receive the administrative request and
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * send back the results.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmdsock_create()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iu_event_id_t eid;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct sockaddr_un laddr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int sock, flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_cmdsock_create()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): socket(AF_UNIX) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Set it to be non-blocking.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou flags = fcntl(sock, F_GETFL, 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) fcntl(sock, F_SETFL, (flags | O_NONBLOCK));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Unlink first in case a previous daemon instance exited ungracefully.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) unlink(VRRPD_SOCKET);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bzero(&laddr, sizeof (laddr));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou laddr.sun_family = AF_UNIX;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(laddr.sun_path, VRRPD_SOCKET, sizeof (laddr.sun_path));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (bind(sock, (struct sockaddr *)&laddr, sizeof (laddr)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): bind() failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(sock);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (listen(sock, 30) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): listen() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(sock);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((eid = iu_register_event(vrrpd_eh, sock, POLLIN,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_cmdsock_handler, NULL)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): iu_register_event()"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou " failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(sock);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_cmdsock_fd = sock;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_cmdsock_eid = eid;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmdsock_destroy()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_cmdsock_destroy()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_unregister_event(vrrpd_eh, vrrpd_cmdsock_eid, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vrrpd_cmdsock_fd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_cmdsock_fd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_cmdsock_eid = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the PF_ROUTER sockets used to listen to the routing socket
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * messages and build the interface/IP address list. Create one for
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * each address family (IPv4 and IPv6).
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_rtsock_create()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int i, flags, sock;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iu_event_id_t eid;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_rtsock_create()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < 2; i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sock = socket(PF_ROUTE, SOCK_RAW, vrrpd_rtsocks[i].vrt_af);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (sock == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): socket() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Set it to be non-blocking.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "fcntl(F_GETFL) failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((fcntl(sock, F_SETFL, flags | O_NONBLOCK)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "fcntl(F_SETFL) failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((eid = iu_register_event(vrrpd_eh, sock, POLLIN,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_rtsock_handler, &(vrrpd_rtsocks[i].vrt_af))) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): register "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "rtsock %d(%s) failed", sock,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou af_str(vrrpd_rtsocks[i].vrt_af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_rtsocks[i].vrt_fd = sock;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_rtsocks[i].vrt_eid = eid;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (i != 2) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(sock);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_rtsock_destroy();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_rtsock_destroy()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int i;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_rtsock_destroy()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < 2; i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_unregister_event(vrrpd_eh, vrrpd_rtsocks[i].vrt_eid,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vrrpd_rtsocks[i].vrt_fd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_rtsocks[i].vrt_eid = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_rtsocks[i].vrt_fd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the VRRP control socket used to bring up/down the virtual
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * IP addresses. It is also used to set the IFF_NOACCEPT flag of
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the virtual IP addresses.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_ctlsock_create()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int s, s6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int on = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): socket(INET) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(s, SOL_SOCKET, SO_VRRP, &on, sizeof (on)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "setsockopt(INET, SO_VRRP) failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(s);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): socket(INET6) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(s);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(s6, SOL_SOCKET, SO_VRRP, &on, sizeof (on)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "setsockopt(INET6, SO_VRRP) failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(s);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(s6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_ctlsock_fd = s;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_ctlsock6_fd = s6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_ctlsock_destroy()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vrrpd_ctlsock_fd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_ctlsock_fd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vrrpd_ctlsock6_fd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_ctlsock6_fd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*ARGSUSED*/
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmd_create(void *arg1, void *arg2, size_t *arg2_sz)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_create_t *cmd = (vrrp_cmd_create_t *)arg1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ret_create_t *ret = (vrrp_ret_create_t *)arg2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_create(&cmd->vcc_conf, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err == VRRP_SUCCESS && cmd->vcc_conf.vvc_enabled) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * No need to update the configuration since it is already
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * done in the above vrrpd_create() call
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_enable(cmd->vcc_conf.vvc_name, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_delete(cmd->vcc_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrc_err = err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*ARGSUSED*/
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmd_delete(void *arg1, void *arg2, size_t *arg2_sz)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_delete_t *cmd = (vrrp_cmd_delete_t *)arg1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ret_delete_t *ret = (vrrp_ret_delete_t *)arg2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrd_err = vrrpd_delete(cmd->vcd_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*ARGSUSED*/
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmd_enable(void *arg1, void *arg2, size_t *arg2_sz)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_enable_t *cmd = (vrrp_cmd_enable_t *)arg1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ret_enable_t *ret = (vrrp_ret_enable_t *)arg2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrs_err = vrrpd_enable(cmd->vcs_name, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*ARGSUSED*/
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmd_disable(void *arg1, void *arg2, size_t *arg2_sz)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_disable_t *cmd = (vrrp_cmd_disable_t *)arg1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ret_disable_t *ret = (vrrp_ret_disable_t *)arg2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrx_err = vrrpd_disable(cmd->vcx_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*ARGSUSED*/
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmd_modify(void *arg1, void *arg2, size_t *arg2_sz)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_modify_t *cmd = (vrrp_cmd_modify_t *)arg1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ret_modify_t *ret = (vrrp_ret_modify_t *)arg2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrm_err = vrrpd_modify(&cmd->vcm_conf, cmd->vcm_mask);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmd_query(void *arg1, void *arg2, size_t *arg2_sz)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_query_t *cmd = (vrrp_cmd_query_t *)arg1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_query(cmd->vcq_name, arg2, arg2_sz);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmd_list(void *arg1, void *arg2, size_t *arg2_sz)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_list_t *cmd = (vrrp_cmd_list_t *)arg1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_list(cmd->vcl_vrid, cmd->vcl_ifname, cmd->vcl_af, arg2, arg2_sz);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Write-type requeset must have the solaris.network.vrrp authorization.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_auth_check(int connfd, vrrp_cmd_info_t *cinfo)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ucred_t *cred = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uid_t uid;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct passwd *pw;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t success = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrp_auth_check()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!cinfo->vi_setop)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Validate the credential
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (getpeerucred(connfd, &cred) == (uid_t)-1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrp_auth_check(): getpeerucred() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((uid = ucred_getruid((const ucred_t *)cred)) == (uid_t)-1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrp_auth_check(): ucred_getruid() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((pw = getpwuid(uid)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrp_auth_check(): getpwuid() failed");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou success = (chkauthattr("solaris.network.vrrp", pw->pw_name) == 1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudone:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ucred_free(cred);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (success);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Process the administrative request from libvrrpadm
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* ARGSUSED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_cmdsock_handler(iu_eh_t *eh, int s, short events, iu_event_id_t id,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou void *arg)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_cmd_info_t *cinfo = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uchar_t buf[BUFFSIZE], ackbuf[BUFFSIZE];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t cursize, acksize, len;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint32_t cmd;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int connfd, i;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct sockaddr_in from;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou socklen_t fromlen;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_cmdsock_handler()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou fromlen = (socklen_t)sizeof (from);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((connfd = accept(s, (struct sockaddr *)&from, &fromlen)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler() accept(): %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * First get the type of the request
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cursize = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (cursize < sizeof (uint32_t)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou len = read(connfd, buf + cursize,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (uint32_t) - cursize);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (len == (size_t)-1 && (errno == EAGAIN || errno == EINTR)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (len > 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cursize += len;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): invalid message "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "length");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(connfd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmd = ((vrrp_cmd_t *)buf)->vc_cmd;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < VRRP_DOOR_INFO_TABLE_SIZE; i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrp_cmd_info_tbl[i].vi_cmd == cmd) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cinfo = vrrp_cmd_info_tbl + i;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (cinfo == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): invalid request "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "type %d", cmd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EINVAL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Get the rest of the request.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(cursize == sizeof (uint32_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (cursize < cinfo->vi_reqsize) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou len = read(connfd, buf + cursize,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cinfo->vi_reqsize - cursize);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (len == (size_t)-1 && (errno == EAGAIN || errno == EINTR)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (len > 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cursize += len;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): invalid message "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "length");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EINVAL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Validate the authorization
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!vrrp_auth_check(connfd, cinfo)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "not sufficient authorization");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EPERM;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudone:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Ack the request
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ((vrrp_ret_t *)ackbuf)->vr_err = err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou acksize = sizeof (vrrp_ret_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If the size of ack is varied, the cmdfunc callback
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * will set the right size.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((acksize = cinfo->vi_acksize) == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou acksize = sizeof (ackbuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cinfo->vi_cmdfunc((vrrp_cmd_t *)buf, ackbuf, &acksize);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Send the ack back.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cursize = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (cursize < acksize) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou len = sendto(connfd, ackbuf + cursize, acksize - cursize,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou 0, (struct sockaddr *)&from, fromlen);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (len == (size_t)-1 && errno == EAGAIN) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (len > 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cursize += len;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler() failed to "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "ack: %s", strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) shutdown(connfd, SHUT_RDWR);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(connfd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Process the routing socket messages and update the interfaces/IP addresses
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * list
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* ARGSUSED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_rtsock_handler(iu_eh_t *eh, int s, short events,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iu_event_id_t id, void *arg)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char buf[BUFFSIZE];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct ifa_msghdr *ifam;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int nbytes;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int af = *(int *)arg;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t scanif = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (;;) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nbytes = read(s, buf, sizeof (buf));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nbytes <= 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* No more messages */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ifam = (struct ifa_msghdr *)buf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ifam->ifam_version != RTM_VERSION) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_rtsock_handler(): version %d "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "not understood", ifam->ifam_version);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_rtsock_handler(): recv %s event",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou rtm_event2str(ifam->ifam_type));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (ifam->ifam_type) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_FREEADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_CHGADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_NEWADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case RTM_DELADDR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * An IP address has been created/updated/deleted or
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * brought up/down, re-initilialize the interface/IP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * address list.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou scanif = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou default:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* Not interesting */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (scanif)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_scan(af);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Periodically scan the interface/IP addresses on the system.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* ARGSUSED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_scan_timer(iu_tq_t *tq, void *arg)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_scan_timer()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_scan(AF_INET);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_scan(AF_INET6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Get the list of the interface/IP addresses of the specified address
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * family.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_scan(int af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_scan(%s)", af_str(af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouagain:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_init_ipcache(af);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* If interface index changes, walk again. */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (vrrpd_walk_addr_info(af) != IPADM_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto again;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_update_ipcache(af);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * First mark all IP addresses of the specific address family to be removed.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * This flag will then be cleared when we walk up all the IP addresses.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_init_ipcache(int af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *intf, *next_intf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip, *nextip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(%s)", af_str(af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou next_intf = TAILQ_FIRST(&vrrp_intf_list);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while ((intf = next_intf) != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou next_intf = TAILQ_NEXT(intf, vvi_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (intf->vvi_af != af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If the interface is still marked as new, it means that this
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * vrrpd_init_ipcache() call is a result of ifindex change,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * which causes the re-walk of all the interfaces (see
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * vrrpd_add_ipaddr()), and some interfaces are still marked
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * as new during the last walk. In this case, delete this
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface with the "update_vr" argument to be _B_FALSE,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * since no VRRP router has been assoicated with this
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface yet (the association is done in
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * vrrpd_update_ipcache()).
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * This interface will be re-added later if it still exists.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (intf->vvi_state == NODE_STATE_NEW) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(): remove %s "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "(%d), may be added later", intf->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifindex);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_if(intf, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (ip = TAILQ_FIRST(&intf->vvi_iplist); ip != NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip = nextip) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nextip = TAILQ_NEXT(ip, vip_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(af, &ip->vip_addr, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ip->vip_state != NODE_STATE_NEW) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(%s/%d, "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%s(%s/0x%x))", intf->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifindex, ip->vip_lifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou abuf, ip->vip_flags);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_state = NODE_STATE_STALE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If the IP is still marked as new, it means that
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * this vrrpd_init_ipcache() call is a result of
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * ifindex change, which causes the re-walk of all
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the IP addresses (see vrrpd_add_ipaddr()).
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Delete this IP.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * This IP will be readded later if it still exists.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(): remove "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%s/%d , %s(%s)", intf->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifindex, ip->vip_lifname, abuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_ip(intf, ip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Walk all the IP addresses of the given family and update its
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * addresses list. Return IPADM_FAILURE if it is required to walk
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * all the interfaces again (one of the interface index changes in between).
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic ipadm_status_t
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyvrrpd_walk_addr_info(int af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *ainfo, *ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char *lifname;
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed struct sockaddr_storage stor;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey vrrp_addr_t *addr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey int ifindex;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey uint64_t flags;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s)", af_str(af));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_addr_info(vrrp_ipadm_handle, NULL, &ainfo, 0, 0);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ipstatus != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_addr_info() failed: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey af_str(af), ipadm_status2str(ipstatus));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (IPADM_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed if (ainfop->ia_ifa.ifa_addr->sa_family != af)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey continue;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey lifname = ainfop->ia_ifa.ifa_name;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey flags = ainfop->ia_ifa.ifa_flags;
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (void) memcpy(&stor, ainfop->ia_ifa.ifa_addr, sizeof (stor));
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed addr = (vrrp_addr_t *)&stor;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey af_str(af), lifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Skip virtual/IPMP/P2P interfaces */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (flags & (IFF_VIRTUAL|IFF_IPMP|IFF_POINTOPOINT)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "skipped %s", af_str(af), lifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Filter out the all-zero IP address */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (VRRPADDR_UNSPECIFIED(af, addr))
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((ifindex = if_nametoindex(lifname)) == 0) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (errno != ENXIO && errno != ENOENT) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "if_nametoindex() failed for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey af_str(af), lifname, strerror(errno));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * The interface is unplumbed/replumbed during the walk. Try
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * to walk the IP addresses one more time.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (vrrpd_add_ipaddr(lifname, af, addr, ifindex, flags)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey == VRRP_EAGAIN) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = IPADM_FAILURE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(ainfo);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (ipstatus);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Given the information of each IP address, update the interface and
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * IP addresses list
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_add_ipaddr(char *lifname, int af, vrrp_addr_t *addr, int ifindex,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t flags)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char ifname[LIFNAMSIZ], *c;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *intf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(af, addr, abuf, INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s, %s, %d, 0x%x)", lifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou abuf, ifindex, flags);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Get the physical interface name from the logical interface name.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(ifname, lifname, sizeof (ifname));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((c = strchr(ifname, ':')) != NULL)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *c = '\0';
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((intf = vrrpd_lookup_if(ifname, af)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(): %s is new", ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_create_if(ifname, af, ifindex, &intf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (intf->vvi_ifindex != ifindex) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If index changes, it means that this interface is
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * unplumbed/replumbed since we last checked. If this
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface is not used by any VRRP router, just
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * update its ifindex, and the IP addresses list will
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * be updated later. Otherwise, return EAGAIN to rewalk
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * all the IP addresses from the beginning.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s) ifindex changed ",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "from %d to %d", ifname, intf->vvi_ifindex, ifindex);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!IS_PRIMARY_INTF(intf) && !IS_VIRTUAL_INTF(intf)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifindex = ifindex;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * delete this interface from the list if this
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface has already been assoicated with
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * any VRRP routers.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_if(intf, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EAGAIN);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Does this IP address already exist?
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(ip, &intf->vvi_iplist, vip_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcmp(ip->vip_lifname, lifname) == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ip != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s, %s) IP exists",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou lifname, abuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_state = NODE_STATE_NONE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_flags = flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ipaddr_cmp(af, addr, &ip->vip_addr) != 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Address has been changed, mark it as new
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If this address is already selected as the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * primary IP address, the new IP will be checked
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * to see whether it is still qualified as the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * primary IP address. If not, the primary IP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * address will be reselected.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&ip->vip_addr, addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vrrp_addr_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_state = NODE_STATE_NEW;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s, %s) IP is new",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou lifname, abuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_create_ip(intf, lifname, addr, flags);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Update the interface and IP addresses list. Remove the ones that have been
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * staled since last time we walk the IP addresses and updated the ones that
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * have been changed.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_update_ipcache(int af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *intf, *nextif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip, *nextip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t primary_selected;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t primary_now_selected;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t need_reenable = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(%s)", af_str(af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nextif = TAILQ_FIRST(&vrrp_intf_list);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while ((intf = nextif) != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nextif = TAILQ_NEXT(intf, vvi_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (intf->vvi_af != af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Does the interface already select its primary IP address?
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou primary_selected = (intf->vvi_pip != NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(!primary_selected || IS_PRIMARY_INTF(intf));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Removed the IP addresses that have been unconfigured.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (ip = TAILQ_FIRST(&intf->vvi_iplist); ip != NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip = nextip) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nextip = TAILQ_NEXT(ip, vip_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ip->vip_state != NODE_STATE_STALE)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(af, &ip->vip_addr, abuf, INET6_ADDRSTRLEN,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): IP %s "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "is removed over %s", abuf, intf->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_ip(intf, ip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * No IP addresses left, delete this interface.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (TAILQ_EMPTY(&intf->vvi_iplist)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "no IP left over %s", intf->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_if(intf, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If this is selected ss the physical interface for any
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * VRRP router, reselect the primary address if needed.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (IS_PRIMARY_INTF(intf)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_reselect_primary(intf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou primary_now_selected = (intf->vvi_pip != NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Cannot find the new primary IP address.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (primary_selected && !primary_now_selected) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "reselect primary IP on %s failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_remove_if(intf, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (!primary_selected && primary_now_selected) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The primary IP address is successfully
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * selected on the physical interfacew we
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * need to walk through all the VRRP routers
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * that is created on this physical interface
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * and see whether they can now be enabled.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou need_reenable = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * For every new virtual IP address, bring up/down it based
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * on the state of VRRP router.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Note that it is fine to not update the IP's vip_flags field
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * even if vrrpd_virtualip_updateone() changed the address's
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * up/down state, since the vip_flags field is only used for
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * select primary IP address over a physical interface, and
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * vrrpd_virtualip_updateone() only affects the virtual IP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * address's status.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (ip = TAILQ_FIRST(&intf->vvi_iplist); ip != NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip = nextip) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nextip = TAILQ_NEXT(ip, vip_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(af, &ip->vip_addr, abuf, INET6_ADDRSTRLEN,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "IP %s over %s%s", abuf, intf->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_state == NODE_STATE_NEW ? " is new" : "");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (IS_VIRTUAL_INTF(intf)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If this IP is new, update its up/down state
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * based on the virtual interface's state
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * (which is determined by the VRRP router's
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * state). Otherwise, check only and prompt
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * warnings if its up/down state has been
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * changed.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_virtualip_updateone(intf, ip,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_state == NODE_STATE_NONE) !=
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "vrrpd_update_ipcache(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "IP %s over %s update failed", abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_ip(intf, ip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_state = NODE_STATE_NONE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The IP address is deleted when it is failed to be brought
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * up. If no IP addresses are left, delete this interface.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (TAILQ_EMPTY(&intf->vvi_iplist)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "no IP left over %s", intf->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_if(intf, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (intf->vvi_state == NODE_STATE_NEW) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * A new interface is found. This interface can be
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the primary interface or the virtual VNIC
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface. Again, we need to walk throught all
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the VRRP routers to see whether some of them can
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * now be enabled because of the new primary IP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * address or the new virtual IP addresses.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_state = NODE_STATE_NONE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou need_reenable = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (need_reenable)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_reenable_all_vr();
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Reselect primary IP if:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - The existing primary IP is no longer qualified (removed or it is down or
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * not a link-local IP for IPv6 VRRP router);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - This is a physical interface but no primary IP is chosen;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_reselect_primary(vrrp_intf_t *intf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(IS_PRIMARY_INTF(intf));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If the interface's old primary IP address is still valid, return
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (((ip = intf->vvi_pip) != NULL) && (QUALIFY_PRIMARY_ADDR(intf, ip)))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ip != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(intf->vvi_af, &ip->vip_addr, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (abuf), _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_reselect_primary(%s): primary IP %s "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "is no longer qualified", intf->vvi_ifname, abuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip = vrrpd_select_primary(intf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf->vvi_pip = ip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ip != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(intf->vvi_af, &ip->vip_addr, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (abuf), _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_reselect_primary(%s): primary IP %s "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "is selected", intf->vvi_ifname, abuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Select the primary IP address. Since the link-local IP address is always
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * at the head of the IP address list, try to find the first UP IP address
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * and see whether it qualify.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_ip_t *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_select_primary(vrrp_intf_t *pif)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *pip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_select_primary(%s)", pif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(pip, &pif->vvi_iplist, vip_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(pip->vip_state != NODE_STATE_STALE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(pif->vvi_af, &pip->vip_addr, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_select_primary(%s): %s is %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_ifname, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (pip->vip_flags & IFF_UP) ? "up" : "down");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pip->vip_flags & IFF_UP)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Is this valid primary IP address?
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pip == NULL || !QUALIFY_PRIMARY_ADDR(pif, pip)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_select_primary(%s/%s) failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_ifname, af_str(pif->vvi_af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (pip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * This is a new interface. Check whether any VRRP router is waiting for it
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_reenable_all_vr()
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_reenable_all_vr()");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_conf.vvc_enabled)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_enable_vr(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If primary_addr_gone is _B_TRUE, it means that we failed to select
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the primary IP address on this (physical) interface; otherwise,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * it means the interface is no longer available.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_remove_if(vrrp_intf_t *intf, boolean_t primary_addr_gone)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_remove_if(%s): %s", intf->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou primary_addr_gone ? "primary address gone" : "interface deleted");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_conf.vvc_enabled)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_disable_vr(vr, intf, primary_addr_gone);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Update the VRRP configuration file based on the given configuration.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * op is either VRRP_CONF_UPDATE or VRRP_CONF_DELETE
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_updateconf(vrrp_vr_conf_t *newconf, uint_t op)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_conf_t conf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou FILE *fp, *nfp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int nfd;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char line[LINE_MAX];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char newfile[MAXPATHLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t found = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_updateconf(%s, %s)", newconf->vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou op == VRRP_CONF_UPDATE ? "update" : "delete");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((fp = fopen(vrrpd_conffile, "r+F")) == NULL) {
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich if (errno != ENOENT) {
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich vrrp_log(VRRP_ERR, "vrrpd_updateconf(): open %s for "
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich "update failed: %s", vrrpd_conffile,
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich strerror(errno));
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich return (VRRP_EDB);
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich }
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich if ((fp = fopen(vrrpd_conffile, "w+F")) == NULL) {
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich vrrp_log(VRRP_ERR, "vrrpd_updateconf(): open %s for "
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich "write failed: %s", vrrpd_conffile,
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich strerror(errno));
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich return (VRRP_EDB);
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) snprintf(newfile, MAXPATHLEN, "%s.new", vrrpd_conffile);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((nfd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): open %s failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou newfile, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) fclose(fp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EDB);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((nfp = fdopen(nfd, "wF")) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): fdopen(%s) failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou newfile, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (fgets(line, sizeof (line), fp) != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf.vvc_vrid = VRRP_VRID_NONE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!found && (err = vrrpd_read_vrconf(line, &conf)) !=
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "configuration format: %s", line);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Write this line out if:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - this is a comment line; or
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - we've done updating/deleting the the given VR; or
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * - if the name of the VR read from this line does not match
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the VR name that we are about to update/delete;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (found || conf.vvc_vrid == VRRP_VRID_NONE ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strcmp(conf.vvc_name, newconf->vvc_name) != 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (fputs(line, nfp) != EOF)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "write line %s", line);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EDB;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Otherwise, update/skip the line.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou found = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (op == VRRP_CONF_DELETE)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(op == VRRP_CONF_UPDATE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_write_vrconf(line, sizeof (line),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou newconf)) != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "update configuration for %s", newconf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (fputs(line, nfp) == EOF) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "write line %s", line);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EDB;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If we get to the end of the file and have not seen the router that
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * we are about to update, write it out.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!found && op == VRRP_CONF_UPDATE) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_write_vrconf(line, sizeof (line),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou newconf)) == VRRP_SUCCESS && fputs(line, nfp) == EOF) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "write line %s", line);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EDB;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (!found && op == VRRP_CONF_DELETE) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to find "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "configuation for %s", newconf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ENOTFOUND;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (fflush(nfp) == EOF || rename(newfile, vrrpd_conffile) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "rename file %s", newfile);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EDB;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudone:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) fclose(fp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) fclose(nfp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) unlink(newfile);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_write_vrconf(char *line, size_t len, vrrp_vr_conf_t *conf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_prop_t *prop;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int n, i;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_write_vrconf(%s)", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < VRRP_PROP_INFO_TABSIZE; i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou prop = &vrrp_prop_info_tbl[i];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou n = snprintf(line, len, i == 0 ? "%s=" : " %s=",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou prop->vs_propname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (n < 0 || n >= len)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou len -= n;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou line += n;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou n = prop->vs_propwrite(conf, line, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (n < 0 || n >= len)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou len -= n;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou line += n;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (i != VRRP_PROP_INFO_TABSIZE) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_write_vrconf(%s): buffer size too"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "small", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EDB);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou n = snprintf(line, len, "\n");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (n < 0 || n >= len) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_write_vrconf(%s): buffer size too"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "small", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EDB);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_read_vrconf(char *line, vrrp_vr_conf_t *conf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char *str, *token;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char *next;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char tmpbuf[MAXLINELEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou str = tmpbuf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(tmpbuf, line, MAXLINELEN);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Skip leading spaces, blank lines, and comments.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou skip_whitespace(str);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((str - tmpbuf == strlen(tmpbuf)) || (*str == '#')) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_vrid = VRRP_VRID_NONE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Read each VR properties.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (token = strtok_r(str, " \n\t", &next); token != NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou token = strtok_r(NULL, " \n\t", &next)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_readprop(token, conf)) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* All properties read but no VRID defined */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err == VRRP_SUCCESS && conf->vvc_vrid == VRRP_VRID_NONE)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_EINVAL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_readprop(const char *str, vrrp_vr_conf_t *conf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_prop_t *prop;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char *pstr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int i;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((pstr = strchr(str, '=')) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_readprop(%s): invalid property", str);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *pstr++ = '\0';
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (i = 0; i < VRRP_PROP_INFO_TABSIZE; i++) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou prop = &vrrp_prop_info_tbl[i];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcasecmp(str, prop->vs_propname) == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (prop->vs_propread(conf, pstr))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (i == VRRP_PROP_INFO_TABSIZE) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_readprop(%s): invalid property", str);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_name(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t size = sizeof (conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (strlcpy(conf->vvc_name, str, size) < size);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_vrid(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_vrid = strtol(str, NULL, 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (!(conf->vvc_vrid < VRRP_VRID_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_vrid > VRRP_VRID_MAX ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_vrid == 0 && errno != 0)));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_af(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcasecmp(str, "AF_INET") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_af = AF_INET;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else if (strcasecmp(str, "AF_INET6") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_af = AF_INET6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_pri(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_pri = strtol(str, NULL, 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (!(conf->vvc_pri < VRRP_PRI_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_pri > VRRP_PRI_OWNER ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_pri == 0 && errno != 0)));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_adver_int(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_adver_int = strtol(str, NULL, 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (!(conf->vvc_adver_int < VRRP_MAX_ADVER_INT_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_adver_int > VRRP_MAX_ADVER_INT_MAX ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_adver_int == 0 && errno != 0)));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_preempt(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcasecmp(str, "true") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_preempt = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else if (strcasecmp(str, "false") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_preempt = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_accept(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcasecmp(str, "true") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_accept = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else if (strcasecmp(str, "false") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_accept = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_enabled(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strcasecmp(str, "enabled") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_enabled = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else if (strcasecmp(str, "disabled") == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_enabled = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (_B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic boolean_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_rd_prop_ifname(vrrp_vr_conf_t *conf, const char *str)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t size = sizeof (conf->vvc_link);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (strlcpy(conf->vvc_link, str, size) < size);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_name(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%s", conf->vvc_name));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_pri(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%d", conf->vvc_pri));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_adver_int(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%d", conf->vvc_adver_int));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_preempt(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_preempt ? "true" : "false"));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_accept(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_accept ? "true" : "false"));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_enabled(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_enabled ? "enabled" : "disabled"));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_vrid(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%d", conf->vvc_vrid));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_af(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_af == AF_INET ? "AF_INET" : "AF_INET6"));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_wt_prop_ifname(vrrp_vr_conf_t *conf, char *str, size_t size)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (snprintf(str, size, "%s", conf->vvc_link));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic char *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouaf_str(int af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (af == 4 || af == AF_INET)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("AF_INET");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else if (af == 6 || af == AF_INET6)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("AF_INET6");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else if (af == AF_UNSPEC)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("AF_UNSPEC");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ("AF_error");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_create_vr(vrrp_vr_conf_t *conf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_create_vr(%s)", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr = malloc(sizeof (vrrp_vr_t))) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_create_vr(): memory allocation for %s"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou " failed", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOMEM);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bzero(vr, sizeof (vrrp_vr_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_state = VRRP_STATE_NONE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timer_id = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_NONE, VRRP_STATE_INIT, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&vr->vvr_conf, conf, sizeof (vrrp_vr_conf_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_enabled = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_INSERT_HEAD(&vrrp_vr_list, vr, vvr_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_delete_vr(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_delete_vr(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_conf.vvc_enabled)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_disable_vr(vr, NULL, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vr->vvr_state == VRRP_STATE_INIT);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_INIT, VRRP_STATE_NONE, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_REMOVE(&vrrp_vr_list, vr, vvr_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) free(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_enable_vr(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t rx_err, tx_err, err = VRRP_EINVAL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_enable_vr(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vr->vvr_conf.vvc_enabled);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * This VRRP router has been successfully enabled and start
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * participating.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_state != VRRP_STATE_INIT)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((rx_err = vrrpd_init_rxsock(vr)) == VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Select the primary IP address. Even if this time
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * primary IP selection failed, we will reselect the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * primary IP address when new IP address comes up.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_reselect_primary(vr->vvr_pif);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_pif->vvi_pip == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_enable_vr(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "select_primary over %s failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, vr->vvr_pif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou rx_err = VRRP_ENOPRIM;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Initialize the TX socket used for this vrrp_vr_t to send the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * multicast packets.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou tx_err = vrrpd_init_txsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Only start the state transition if sockets for both RX and TX are
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * initialized correctly.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (rx_err != VRRP_SUCCESS || tx_err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Record the error information for diagnose purpose.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = (rx_err == VRRP_SUCCESS) ? tx_err : rx_err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_conf.vvc_pri == 255)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_state_i2m(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_state_i2b(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_pif->vvi_pip = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini_txsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini_rxsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Given the removed interface, see whether the given VRRP router would
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * be affected and stop participating the VRRP protocol.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If intf is NULL, VR disabling request is coming from the admin.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_disable_vr(vrrp_vr_t *vr, vrrp_intf_t *intf, boolean_t primary_addr_gone)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_disable_vr(%s): %s%s", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf == NULL ? "requested by admin" : intf->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou intf == NULL ? "" : (primary_addr_gone ? "primary address gone" :
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "interface deleted"));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * An interface is deleted, see whether this interface is the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * physical interface or the VNIC of the given VRRP router.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If so, continue to disable the VRRP router.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!primary_addr_gone && (intf != NULL) && (intf != vr->vvr_pif) &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (intf != vr->vvr_vif)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If this is the case that the primary IP address is gone,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * and we failed to reselect another primary IP address,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * continue to disable the VRRP router.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (primary_addr_gone && intf != vr->vvr_pif)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): disabling",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_state == VRRP_STATE_MASTER) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If this router is disabled by the administrator, send
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the zero-priority advertisement to indicate the Master
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * stops participating VRRP.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (intf == NULL)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_send_adv(vr, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_m2i(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (vr->vvr_state == VRRP_STATE_BACKUP) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_b2i(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If no primary IP address can be selected, the VRRP router
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * stays at the INIT state and will become BACKUP and MASTER when
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * a primary IP address is reselected.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (primary_addr_gone) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): primary IP "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "is removed", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = VRRP_ENOPRIM;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (intf == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The VRRP router is disable by the administrator
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): disabled by admin",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini_txsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini_rxsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (intf == vr->vvr_pif) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): physical interface "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%s removed", vr->vvr_conf.vvc_name, intf->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = VRRP_ENOPRIM;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini_rxsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (intf == vr->vvr_vif) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): VNIC interface %s"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou " removed", vr->vvr_conf.vvc_name, intf->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = VRRP_ENOVIRT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini_txsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_create(vrrp_vr_conf_t *conf, boolean_t updateconf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_create(%s, %s, %d)", conf->vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_link, conf->vvc_vrid);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(conf != NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Sanity check
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((strlen(conf->vvc_name) == 0) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (strlen(conf->vvc_link) == 0) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_vrid < VRRP_VRID_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_vrid > VRRP_VRID_MAX) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_pri < VRRP_PRI_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_pri > VRRP_PRI_OWNER) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_adver_int < VRRP_MAX_ADVER_INT_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_adver_int > VRRP_MAX_ADVER_INT_MAX) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_af != AF_INET && conf->vvc_af != AF_INET6) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_pri == VRRP_PRI_OWNER && !conf->vvc_accept)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_create(%s): invalid argument",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!vrrp_valid_name(conf->vvc_name)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_create(): %s is not a valid router "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "name", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVALVRNAME);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_lookup_vr_by_name(conf->vvc_name) != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_create(): %s already exists",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINSTEXIST);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrpd_lookup_vr_by_vrid(conf->vvc_link, conf->vvc_vrid,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_af) != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_create(): VRID %d/%s over %s "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "already exists", conf->vvc_vrid, af_str(conf->vvc_af),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_link);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EVREXIST);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (updateconf && (err = vrrpd_updateconf(conf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRP_CONF_UPDATE)) != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_create(): failed to update "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "configuration for %s", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_create_vr(conf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS && updateconf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_updateconf(conf, VRRP_CONF_DELETE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_delete(const char *vn)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_delete(%s)", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_delete(): %s not exists", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOTFOUND);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_updateconf(&vr->vvr_conf, VRRP_CONF_DELETE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_delete(): failed to delete "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "configuration for %s", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_vr(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_enable(const char *vn, boolean_t updateconf)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_conf_t *conf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint32_t flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou datalink_class_t class;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_enable(%s)", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_enable(): %s does not exist", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOTFOUND);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The VR is already enabled.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf = &vr->vvr_conf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (conf->vvc_enabled) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_enable(): %s is already "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "enabled", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EALREADY);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Check whether the link exists.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((strlen(conf->vvc_link) == 0) || dladm_name2info(vrrpd_vh->vh_dh,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_link, NULL, &flags, &class, NULL) != DLADM_STATUS_OK ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou !(flags & DLADM_OPT_ACTIVE) || ((class != DATALINK_CLASS_PHYS) &&
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich (class != DATALINK_CLASS_VLAN) && (class != DATALINK_CLASS_AGGR) &&
2954adb080121c02025bb94537c313e6f51c9fd7Rob Gulewich (class != DATALINK_CLASS_VNIC))) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_enable(%s): invalid link %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vn, conf->vvc_link);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVALLINK);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Get the associated VNIC name by the given interface/vrid/
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * address famitly.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrp_get_vnicname(vrrpd_vh, conf->vvc_vrid,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_af, conf->vvc_link, NULL, NULL, vr->vvr_vnic,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (vr->vvr_vnic));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_enable(%s): no VNIC for VRID %d/%s "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "over %s", vn, conf->vvc_vrid, af_str(conf->vvc_af),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_link);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ENOVNIC;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Find the right VNIC, primary interface and get the list of the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * protected IP adressses and primary IP address. Note that if
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * either interface is NULL (no IP addresses configured over the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface), we will still continue and mark this VRRP router
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * as "enabled".
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_enabled = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (updateconf && (err = vrrpd_updateconf(&vr->vvr_conf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRP_CONF_UPDATE)) != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_enable(): failed to update "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "configuration for %s", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto fail;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If vrrpd_setup_vr() fails, it is possible that there is no IP
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * addresses over ether the primary interface or the VNIC yet,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * return success in this case, the VRRP router will stay in
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the initialized state and start to work when the IP address is
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * configured.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_enable_vr(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoufail:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_enabled = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_vnic[0] = '\0';
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_disable(const char *vn)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_disable(%s)", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_disable(): %s does not exist", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOTFOUND);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The VR is already disable.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!vr->vvr_conf.vvc_enabled) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_disable(): %s was not enabled", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EALREADY);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_enabled = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_updateconf(&vr->vvr_conf, VRRP_CONF_UPDATE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_enabled = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_disable(): failed to update "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "configuration for %s", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_disable_vr(vr, NULL, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_vnic[0] = '\0';
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_modify(vrrp_vr_conf_t *conf, uint32_t mask)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_conf_t savconf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int pri;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou boolean_t accept, set_accept = _B_FALSE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_modify(%s)", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr = vrrpd_lookup_vr_by_name(conf->vvc_name)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_modify(): cannot find the given "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "VR instance: %s", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOTFOUND);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask & VRRP_CONF_INTERVAL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (conf->vvc_adver_int < VRRP_MAX_ADVER_INT_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_adver_int > VRRP_MAX_ADVER_INT_MAX) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_modify(%s): invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "adver_interval %d", conf->vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_adver_int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pri = vr->vvr_conf.vvc_pri;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask & VRRP_CONF_PRIORITY) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (conf->vvc_pri < VRRP_PRI_MIN ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_pri > VRRP_PRI_OWNER) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_modify(%s): invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "priority %d", conf->vvc_name, conf->vvc_pri);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pri = conf->vvc_pri;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou accept = vr->vvr_conf.vvc_accept;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask & VRRP_CONF_ACCEPT)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou accept = conf->vvc_accept;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pri == VRRP_PRI_OWNER && !accept) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_modify(%s): accept mode must be "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "true for VRRP address owner", conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((mask & VRRP_CONF_ACCEPT) && (vr->vvr_conf.vvc_accept != accept)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_set_noaccept(vr, !accept);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_modify(%s): access mode "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "updating failed: %s", conf->vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou set_accept = _B_TRUE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Save the current configuration, so it can be restored if the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * following fails.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&savconf, &vr->vvr_conf, sizeof (vrrp_vr_conf_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask & VRRP_CONF_PREEMPT)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_preempt = conf->vvc_preempt;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask & VRRP_CONF_ACCEPT)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_accept = accept;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask & VRRP_CONF_PRIORITY)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_pri = pri;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (mask & VRRP_CONF_INTERVAL)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_adver_int = conf->vvc_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_updateconf(&vr->vvr_conf, VRRP_CONF_UPDATE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_modify(%s): configuration update "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", conf->vvc_name, vrrp_err2str(err));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (set_accept)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_set_noaccept(vr, accept);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&vr->vvr_conf, &savconf, sizeof (vrrp_vr_conf_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((mask & VRRP_CONF_PRIORITY) && (vr->vvr_state == VRRP_STATE_BACKUP))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((mask & VRRP_CONF_INTERVAL) && (vr->vvr_state == VRRP_STATE_MASTER))
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = conf->vvc_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_list(vrid_t vrid, char *ifname, int af, vrrp_ret_list_t *ret,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t *sizep)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char *p = (char *)ret + sizeof (vrrp_ret_list_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t size = (*sizep) - sizeof (vrrp_ret_list_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_list(%d_%s_%s)", vrid, ifname, af_str(af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrl_cnt = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrid != VRRP_VRID_NONE && vr->vvr_conf.vvc_vrid != vrid)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (strlen(ifname) != 0 && strcmp(ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_link) == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((af == AF_INET || af == AF_INET6) &&
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_af != af)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou continue;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (size < VRRP_NAME_MAX) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_list(): buffer size too "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "small to hold %d router names", ret->vrl_cnt);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *sizep = sizeof (vrrp_ret_list_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrl_err = VRRP_ETOOSMALL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(p, vr->vvr_conf.vvc_name, VRRP_NAME_MAX);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou p += (strlen(vr->vvr_conf.vvc_name) + 1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrl_cnt++;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size -= VRRP_NAME_MAX;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *sizep = sizeof (vrrp_ret_list_t) + ret->vrl_cnt * VRRP_NAME_MAX;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_list() return %d", ret->vrl_cnt);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrl_err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_query(const char *vn, vrrp_ret_query_t *ret, size_t *sizep)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_queryinfo_t *infop;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct timeval now;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint32_t vipcnt = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t size = *sizep;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_query(%s)", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_query(): %s does not exist", vn);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *sizep = sizeof (vrrp_ret_query_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrq_err = VRRP_ENOTFOUND;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Get the virtual IP list if the router is not in the INIT state.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_state != VRRP_STATE_INIT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif = vr->vvr_vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(ip, &vif->vvi_iplist, vip_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vipcnt++;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *sizep = sizeof (vrrp_ret_query_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *sizep += (vipcnt == 0) ? 0 : (vipcnt - 1) * sizeof (vrrp_addr_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (*sizep > size) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_query(): not enough space to hold "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%d virtual IPs", vipcnt);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *sizep = sizeof (vrrp_ret_query_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrq_err = VRRP_ETOOSMALL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) gettimeofday(&now, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bzero(ret, *sizep);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou infop = &ret->vrq_qinfo;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&infop->show_vi,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &(vr->vvr_conf), sizeof (vrrp_vr_conf_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&infop->show_vs,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &(vr->vvr_sinfo), sizeof (vrrp_stateinfo_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strlcpy(infop->show_va.va_vnic, vr->vvr_vnic, MAXLINKNAMELEN);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou infop->show_vt.vt_since_last_tran = timeval_to_milli(
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou timeval_delta(now, vr->vvr_sinfo.vs_st_time));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_state == VRRP_STATE_INIT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrq_err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vipcnt = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(ip, &vif->vvi_iplist, vip_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&infop->show_va.va_vips[vipcnt++],
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &ip->vip_addr, sizeof (vrrp_addr_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou infop->show_va.va_vipcnt = vipcnt;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&infop->show_va.va_primary,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vr->vvr_pif->vvi_pip->vip_addr, sizeof (vrrp_addr_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&infop->show_vp, &(vr->vvr_peer), sizeof (vrrp_peer_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Check whether there is a peer.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!VRRPADDR_UNSPECIFIED(vr->vvr_conf.vvc_af,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &(vr->vvr_peer.vp_addr))) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou infop->show_vt.vt_since_last_adv = timeval_to_milli(
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou timeval_delta(now, vr->vvr_peer.vp_time));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_state == VRRP_STATE_BACKUP) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou infop->show_vt.vt_master_down_intv =
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou MASTER_DOWN_INTERVAL_VR(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ret->vrq_err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Build the VRRP packet (not including the IP header). Return the
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * payload length.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If zero_pri is set to be B_TRUE, then this is the specical zero-priority
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * advertisement which is sent by the Master to indicate that it has been
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * stopped participating in VRRP.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic size_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_build_vrrp(vrrp_vr_t *vr, uchar_t *buf, int buflen, boolean_t zero_pri)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_pkt_t *vp = (vrrp_pkt_t *)buf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in_addr *a4 = (struct in_addr *)(vp + 1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in6_addr *a6 = (struct in6_addr *)(vp + 1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif = vr->vvr_vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *vip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int af = vif->vvi_af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t size = sizeof (vrrp_pkt_t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t rsvd_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int nip = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_build_vrrp(%s, %s_priority): intv %d",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, zero_pri ? "zero" : "non-zero",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_adver_int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou TAILQ_FOREACH(vip, &vif->vvi_iplist, vip_next) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((size += ((af == AF_INET) ? sizeof (struct in_addr) :
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (struct in6_addr))) > buflen) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_build_vrrp(%s): buffer size "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "not big enough %d", vr->vvr_conf.vvc_name, size);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (af == AF_INET)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou a4[nip++] = vip->vip_addr.in4.sin_addr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou a6[nip++] = vip->vip_addr.in6.sin6_addr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nip == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_build_vrrp(%s): no virtual IP "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "address", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_vers_type = (VRRP_VERSION << 4) | VRRP_PKT_ADVERT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_vrid = vr->vvr_conf.vvc_vrid;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_prio = zero_pri ? VRRP_PRIO_ZERO : vr->vvr_conf.vvc_pri;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou rsvd_adver_int = MSEC2CENTISEC(vr->vvr_conf.vvc_adver_int) & 0x0fff;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_rsvd_adver_int = htons(rsvd_adver_int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_ipnum = nip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Set the checksum to 0 first, then caculate it.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_chksum = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (af == AF_INET) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_chksum = vrrp_cksum4(
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vr->vvr_pif->vvi_pip->vip_addr.in4.sin_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vrrp_muladdr4.in4.sin_addr, size, vp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_chksum = vrrp_cksum6(
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vr->vvr_pif->vvi_pip->vip_addr.in6.sin6_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vrrp_muladdr6.in6.sin6_addr, size, vp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (size);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * We need to build the IPv4 header on our own.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_send_adv_v4(vrrp_vr_t *vr, uchar_t *buf, size_t len, boolean_t zero_pri)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct ip *ip = (struct ip *)buf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t plen;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v4(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((plen = vrrpd_build_vrrp(vr, buf + sizeof (struct ip),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou len - sizeof (struct ip), zero_pri)) == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ETOOSMALL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_hl = sizeof (struct ip) >> 2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_v = IPV4_VERSION;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_tos = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou plen += sizeof (struct ip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_len = htons(plen);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_off = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_ttl = VRRP_IP_TTL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_p = IPPROTO_VRRP;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_src = vr->vvr_pif->vvi_pip->vip_addr.in4.sin_addr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_dst = vrrp_muladdr4.in4.sin_addr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The kernel will set the IP cksum and the IPv4 identification.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_id = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->ip_sum = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((len = sendto(vr->vvr_vif->vvi_sockfd, buf, plen, 0,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (const struct sockaddr *)&vrrp_muladdr4,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (struct sockaddr_in))) != plen) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_send_adv_v4(): sendto() on "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "(vrid:%d, %s, %s) failed: %s sent:%d expect:%d",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_vrid, vr->vvr_vif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou af_str(vr->vvr_conf.vvc_af), strerror(errno), len, plen);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v4(%s) succeed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_send_adv_v6(vrrp_vr_t *vr, uchar_t *buf, size_t len, boolean_t zero_pri)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct msghdr msg6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t hoplimit_space = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t pktinfo_space = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t bufspace = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in6_pktinfo *pktinfop;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct cmsghdr *cmsgp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uchar_t *cmsg_datap;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct iovec iov;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou size_t plen;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v6(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((plen = vrrpd_build_vrrp(vr, buf, len, zero_pri)) == 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ETOOSMALL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_control = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_controllen = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou hoplimit_space = sizeof (int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bufspace += sizeof (struct cmsghdr) + _MAX_ALIGNMENT +
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou hoplimit_space + _MAX_ALIGNMENT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pktinfo_space = sizeof (struct in6_pktinfo);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bufspace += sizeof (struct cmsghdr) + _MAX_ALIGNMENT +
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pktinfo_space + _MAX_ALIGNMENT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * We need to temporarily set the msg6.msg_controllen to bufspace
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * (we will later trim it to actual length used). This is needed because
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * CMSG_NXTHDR() uses it to check we have not exceeded the bounds.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bufspace += sizeof (struct cmsghdr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_controllen = bufspace;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_control = (struct cmsghdr *)malloc(bufspace);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (msg6.msg_control == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_send_adv_v6(%s): memory allocation "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOMEM);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp = CMSG_FIRSTHDR(&msg6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp->cmsg_level = IPPROTO_IPV6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp->cmsg_type = IPV6_HOPLIMIT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsg_datap = CMSG_DATA(cmsgp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *(int *)cmsg_datap = VRRP_IP_TTL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp->cmsg_len = cmsg_datap + hoplimit_space - (uchar_t *)cmsgp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp = CMSG_NXTHDR(&msg6, cmsgp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp->cmsg_level = IPPROTO_IPV6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp->cmsg_type = IPV6_PKTINFO;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsg_datap = CMSG_DATA(cmsgp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pktinfop = (struct in6_pktinfo *)cmsg_datap;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * We don't know if pktinfop->ipi6_addr is aligned properly,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * therefore let's use bcopy, instead of assignment.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) bcopy(&vr->vvr_pif->vvi_pip->vip_addr.in6.sin6_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &pktinfop->ipi6_addr, sizeof (struct in6_addr));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * We can assume pktinfop->ipi6_ifindex is 32 bit aligned.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pktinfop->ipi6_ifindex = vr->vvr_vif->vvi_ifindex;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp->cmsg_len = cmsg_datap + pktinfo_space - (uchar_t *)cmsgp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp = CMSG_NXTHDR(&msg6, cmsgp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_controllen = (char *)cmsgp - (char *)msg6.msg_control;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_name = &vrrp_muladdr6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_namelen = sizeof (struct sockaddr_in6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iov.iov_base = buf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iov.iov_len = plen;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_iov = &iov;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg6.msg_iovlen = 1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((len = sendmsg(vr->vvr_vif->vvi_sockfd,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (const struct msghdr *)&msg6, 0)) != plen) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_send_adv_v6(%s): sendmsg() failed: "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%s expect %d sent %d", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno), plen, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) free(msg6.msg_control);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v6(%s) succeed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) free(msg6.msg_control);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Send the VRRP advertisement packets.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_send_adv(vrrp_vr_t *vr, boolean_t zero_pri)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t buf[(IP_MAXPACKET + 1)/8];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_send_adv(%s, %s_priority)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, zero_pri ? "zero" : "non_zero");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vr->vvr_pif->vvi_pip != NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_pif->vvi_pip == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_send_adv(%s): no primary IP "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "address", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_conf.vvc_af == AF_INET) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (vrrpd_send_adv_v4(vr, (uchar_t *)buf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (buf), zero_pri));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (vrrpd_send_adv_v6(vr, (uchar_t *)buf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (buf), zero_pri));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_process_adv(vrrp_vr_t *vr, vrrp_addr_t *from, vrrp_pkt_t *vp)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_conf_t *conf = &vr->vvr_conf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char peer[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char local[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int addr_cmp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t peer_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(vr->vvr_conf.vvc_af, from, peer, INET6_ADDRSTRLEN,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s) from %s", conf->vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou peer);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_state <= VRRP_STATE_INIT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): state: %s, not "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "ready", conf->vvc_name, vrrp_state2str(vr->vvr_state));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou peer_adver_int = CENTISEC2MSEC(ntohs(vp->vp_rsvd_adver_int) & 0x0fff);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(vr->vvr_pif->vvi_af, &vr->vvr_pif->vvi_pip->vip_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou local, INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): local/state/pri"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "(%s/%s/%d) peer/pri/intv(%s/%d/%d)", conf->vvc_name, local,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_state2str(vr->vvr_state), conf->vvc_pri, peer,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_prio, peer_adver_int);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou addr_cmp = ipaddr_cmp(vr->vvr_pif->vvi_af, from,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vr->vvr_pif->vvi_pip->vip_addr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (addr_cmp == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): local message",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (conf->vvc_pri == vp->vp_prio) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): peer IP %s is %s"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou " than the local IP %s", conf->vvc_name, peer,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou addr_cmp > 0 ? "greater" : "less", local);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (conf->vvc_pri == 255) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv(%s): virtual address "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "owner received advertisement from %s", conf->vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou peer);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) gettimeofday(&vr->vvr_peer_time, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&vr->vvr_peer_addr, from, sizeof (vrrp_addr_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_peer_prio = vp->vp_prio;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_peer_adver_int = peer_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_state == VRRP_STATE_BACKUP) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_master_adver_int = vr->vvr_peer_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vp->vp_prio == VRRP_PRIO_ZERO) ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (conf->vvc_preempt == _B_FALSE ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_prio >= conf->vvc_pri)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_cancel_timer(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timer_id, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vp->vp_prio == VRRP_PRIO_ZERO) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* the master stops participating in VRRP */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = SKEW_TIME_VR(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr->vvr_timer_id = iu_schedule_timer_ms(
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_timerq, vr->vvr_timeout, vrrp_b2m_timeout,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "start vrrp_b2m_timeout(%d) failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_name, vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "start vrrp_b2m_timeout(%d)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_name, vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (vr->vvr_state == VRRP_STATE_MASTER) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vp->vp_prio == VRRP_PRIO_ZERO) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_send_adv(vr, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_cancel_timer(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timer_id, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr->vvr_timer_id = iu_schedule_timer_ms(
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_timerq, vr->vvr_timeout, vrrp_adv_timeout,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "start vrrp_adv_timeout(%d) failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_name, vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "start vrrp_adv_timeout(%d)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou conf->vvc_name, vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (vp->vp_prio > conf->vvc_pri ||
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (vp->vp_prio == conf->vvc_pri && addr_cmp > 0)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_state_m2b(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(_B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_process_vrrp(vrrp_intf_t *pif, vrrp_pkt_t *vp, size_t len,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_addr_t *from)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint8_t vers_type;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t saved_cksum, cksum;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char peer[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(pif->vvi_af, from, peer, INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_process_vrrp(%s) from %s", pif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou peer);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (len < sizeof (vrrp_pkt_t)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s): invalid message "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "length %d", len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Verify: VRRP version number and packet type.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vers_type = ((vp->vp_vers_type & VRRP_VER_MASK) >> 4);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vers_type != VRRP_VERSION) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s) unsupported "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "version %d", pif->vvi_ifname, vers_type);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vp->vp_ipnum == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s): zero IPvX count",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (len - sizeof (vrrp_pkt_t) !=
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_ipnum * (pif->vvi_af == AF_INET ? sizeof (struct in_addr) :
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (struct in6_addr))) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s): invalid IPvX count"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou " %d", pif->vvi_ifname, vp->vp_ipnum);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vers_type = (vp->vp_vers_type & VRRP_TYPE_MASK);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * verify: VRRP checksum. Note that vrrp_cksum returns network byte
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * order checksum value;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou saved_cksum = vp->vp_chksum;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vp->vp_chksum = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pif->vvi_af == AF_INET) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cksum = vrrp_cksum4(&from->in4.sin_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vrrp_muladdr4.in4.sin_addr, len, vp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cksum = vrrp_cksum6(&from->in6.sin6_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vrrp_muladdr6.in6.sin6_addr, len, vp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (cksum != saved_cksum) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s) invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "checksum: expected/real(0x%x/0x%x)", pif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cksum, saved_cksum);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr = vrrpd_lookup_vr_by_vrid(pif->vvi_ifname, vp->vp_vrid,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_af)) != NULL && vers_type == VRRP_PKT_ADVERT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_process_adv(vr, from, vp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_vrrp(%s) VRID(%d/%s) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "not configured", pif->vvi_ifname, vp->vp_vrid,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou af_str(pif->vvi_af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * IPv4 socket, the IPv4 header is included.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_process_adv_v4(vrrp_intf_t *pif, struct msghdr *msgp, size_t len)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct ip *ip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_process_adv_v4(%s, %d)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_ifname, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip = (struct ip *)msgp->msg_iov->iov_base;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* Sanity check */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (len < sizeof (struct ip) || len < ntohs(ip->ip_len)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid length "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%d", pif->vvi_ifname, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(ip->ip_v == IPV4_VERSION);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(ip->ip_p == IPPROTO_VRRP);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(msgp->msg_namelen == sizeof (struct sockaddr_in));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrp_muladdr4.in4.sin_addr.s_addr != ip->ip_dst.s_addr) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "destination %s", pif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou inet_ntop(pif->vvi_af, &(ip->ip_dst), abuf, sizeof (abuf)));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ip->ip_ttl != VRRP_IP_TTL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "ttl %d", pif->vvi_ifname, ip->ip_ttl);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Note that the ip_len contains only the IP payload length.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (vrrpd_process_vrrp(pif,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (vrrp_pkt_t *)((char *)ip + ip->ip_hl * 4), ntohs(ip->ip_len),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (vrrp_addr_t *)msgp->msg_name));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * IPv6 socket, check the ancillary_data.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_process_adv_v6(vrrp_intf_t *pif, struct msghdr *msgp, size_t len)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct cmsghdr *cmsgp;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uchar_t *cmsg_datap;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in6_pktinfo *pktinfop;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int ttl;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_process_adv_v6(%s, %d)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_ifname, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* Sanity check */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (len < sizeof (vrrp_pkt_t)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv_v6(%s): invalid length "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%d", pif->vvi_ifname, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(msgp->msg_namelen == sizeof (struct sockaddr_in6));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (cmsgp = CMSG_FIRSTHDR(msgp); cmsgp != NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsgp = CMSG_NXTHDR(msgp, cmsgp)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(cmsgp->cmsg_level == IPPROTO_IPV6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou cmsg_datap = CMSG_DATA(cmsgp);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (cmsgp->cmsg_type) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case IPV6_HOPLIMIT:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((ttl = *(int *)cmsg_datap) == VRRP_IP_TTL)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "ttl %d", pif->vvi_ifname, ttl);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case IPV6_PKTINFO:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_BAD_PTR_CAST_ALIGN */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pktinfop = (struct in6_pktinfo *)cmsg_datap;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (IN6_ARE_ADDR_EQUAL(&pktinfop->ipi6_addr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vrrp_muladdr6.in6.sin6_addr)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "destination %s", pif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou inet_ntop(pif->vvi_af, &pktinfop->ipi6_addr, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (abuf)));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_EINVAL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (vrrpd_process_vrrp(pif, msgp->msg_iov->iov_base, len,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msgp->msg_name));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* ARGSUSED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_sock_handler(iu_eh_t *eh, int s, short events, iu_event_id_t id,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou void *arg)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct msghdr msg;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_addr_t from;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t buf[(IP_MAXPACKET + 1)/8];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t ancillary_data[(IP_MAXPACKET + 1)/8];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *pif = arg;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int af = pif->vvi_af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int len;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct iovec iov;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_sock_handler(%s)", pif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg.msg_name = (struct sockaddr *)&from;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg.msg_namelen = (af == AF_INET) ? sizeof (struct sockaddr_in) :
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (struct sockaddr_in6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iov.iov_base = (char *)buf;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou iov.iov_len = sizeof (buf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg.msg_iov = &iov;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg.msg_iovlen = 1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg.msg_control = ancillary_data;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou msg.msg_controllen = sizeof (ancillary_data);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((len = recvmsg(s, &msg, 0)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_sock_handler() recvmsg(%s) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", pif->vvi_ifname, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Ignore packets whose control buffers that don't fit
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_sock_handler() %s buffer not "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "big enough", pif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (af == AF_INET)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_process_adv_v4(pif, &msg, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_process_adv_v6(pif, &msg, len);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the socket which is used to receive VRRP packets. Virtual routers
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * that configured on the same physical interface share the same socket.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_init_rxsock(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *pif; /* Physical interface used to recv packets */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct group_req greq;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct sockaddr_storage *muladdr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int af, proto;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int on = 1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The RX sockets may already been initialized.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((pif = vr->vvr_pif) != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s) already done on %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, pif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(pif->vvi_sockfd != -1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * If no IP addresses configured on the primary interface,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * return failure.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou af = vr->vvr_conf.vvc_af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif = vrrpd_lookup_if(vr->vvr_conf.vvc_link, af);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pif == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s): no IP address "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "over %s/%s", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_link, af_str(af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOPRIM);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou proto = (af == AF_INET ? IPPROTO_IP : IPPROTO_IPV6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pif->vvi_nvr++ == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(pif->vvi_sockfd < 0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_sockfd = socket(af, SOCK_RAW, IPPROTO_VRRP);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pif->vvi_sockfd < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): socket() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed %s", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Join the multicast group to receive VRRP packets.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (af == AF_INET) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou muladdr = (struct sockaddr_storage *)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void *)&vrrp_muladdr4;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou muladdr = (struct sockaddr_storage *)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void *)&vrrp_muladdr6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou greq.gr_interface = pif->vvi_ifindex;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) memcpy(&greq.gr_group, muladdr,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (struct sockaddr_storage));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(pif->vvi_sockfd, proto, MCAST_JOIN_GROUP, &greq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (struct group_req)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "join_group(%d) failed: %s", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_ifindex, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "join_group(%d) succeeded", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_ifindex);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Unlike IPv4, the IPv6 raw socket does not pass the IP header
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * when a packet is received. Call setsockopt() to receive such
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * information.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (af == AF_INET6) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Enable receipt of destination address info
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(pif->vvi_sockfd, proto, IPV6_RECVPKTINFO,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (char *)&on, sizeof (on)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "enable recvpktinfo failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Enable receipt of hoplimit info
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(pif->vvi_sockfd, proto,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou IPV6_RECVHOPLIMIT, (char *)&on, sizeof (on)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "enable recvhoplimit failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((pif->vvi_eid = iu_register_event(vrrpd_eh,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_sockfd, POLLIN, vrrpd_sock_handler, pif)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "iu_register_event() failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s) over %s already "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "done %d", vr->vvr_conf.vvc_name, pif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_nvr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(IS_PRIMARY_INTF(pif));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudone:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_pif = pif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_fini_rxsock(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Delete the socket which is used to receive VRRP packets for the given
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * VRRP router. Since all virtual routers that configured on the same
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * physical interface share the same socket, the socket is only closed
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * when the last VRRP router share this socket is deleted.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_fini_rxsock(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *pif = vr->vvr_pif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_fini_rxsock(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (pif == NULL)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (--pif->vvi_nvr == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_fini_rxsock(%s) over %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, pif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_unregister_event(vrrpd_eh, pif->vvi_eid, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(pif->vvi_sockfd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_pip = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_sockfd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou pif->vvi_eid = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_fini_rxsock(%s) over %s %d",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, pif->vvi_ifname, pif->vvi_nvr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_pif = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the socket which is used to send VRRP packets. Further, set
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the IFF_NOACCEPT flag based on the VRRP router's accept mode.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_init_txsock(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_vif != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock(%s) already done on %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, vr->vvr_vif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou af = vr->vvr_conf.vvc_af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vif = vrrpd_lookup_if(vr->vvr_vnic, af)) == NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock(%s) no IP address over "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%s/%s", vr->vvr_conf.vvc_name, vr->vvr_vnic, af_str(af));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOVIRT);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_vif = vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vr->vvr_conf.vvc_af == AF_INET)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_init_txsock_v4(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_init_txsock_v6(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The interface should start with IFF_NOACCEPT flag not set, only
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * call this function when the VRRP router requires IFF_NOACCEPT.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!vr->vvr_conf.vvc_accept)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_set_noaccept(vr, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudone:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vif->vvi_sockfd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_sockfd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_vif = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the IPv4 socket which is used to send VRRP packets. Note that
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the destination MAC address of VRRP advertisement must be the virtual
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * MAC address, so we specify the output interface to be the specific VNIC.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_init_txsock_v4(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif; /* VNIC interface used to send packets */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *vip; /* The first IP over the VNIC */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int on = 1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char off = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif = vr->vvr_vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vr->vvr_conf.vvc_af == AF_INET);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vif != NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v4(%s) over %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, vif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vif->vvi_sockfd != -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v4(%s) already done "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "over %s", vr->vvr_conf.vvc_name, vif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_sockfd = socket(vif->vvi_af, SOCK_RAW, IPPROTO_VRRP);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vif->vvi_sockfd < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): socket() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Include the IP header, so that we can specify the IP address/ttl.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(vif->vvi_sockfd, IPPROTO_IP, IP_HDRINCL, (char *)&on,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (on)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): ip_hdrincl "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Disable multicast loopback.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(vif->vvi_sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &off,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (char)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): disable "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "multicast_loop failed: %s", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vip = TAILQ_FIRST(&vif->vvi_iplist);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(vif->vvi_af, &vip->vip_addr, abuf, INET6_ADDRSTRLEN,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Set the output interface to send the VRRP packet.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(vif->vvi_sockfd, IPPROTO_IP, IP_MULTICAST_IF,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vip->vip_addr.in4.sin_addr, sizeof (struct in_addr)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): multcast_if(%s) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", vr->vvr_conf.vvc_name, abuf, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_init_txsock_v4(%s): multcast_if(%s) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "succeed", vr->vvr_conf.vvc_name, abuf);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudone:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vif->vvi_sockfd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_sockfd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Create the IPv6 socket which is used to send VRRP packets. Note that
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the destination must be the virtual MAC address, so we specify the output
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * interface to be the specific VNIC.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_init_txsock_v6(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif; /* VNIC interface used to send packets */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int off = 0, ttl = VRRP_IP_TTL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif = vr->vvr_vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vr->vvr_conf.vvc_af == AF_INET6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vif != NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v6(%s) over %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, vif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vif->vvi_sockfd != -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v6(%s) already done "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "over %s", vr->vvr_conf.vvc_name, vif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_sockfd = socket(vif->vvi_af, SOCK_RAW, IPPROTO_VRRP);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vif->vvi_sockfd < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): socket() "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Disable multicast loopback.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(vif->vvi_sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &off, sizeof (int)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): disable "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "multicast_loop failed: %s", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Set the multicast TTL.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(vif->vvi_sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &ttl, sizeof (int)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): enable "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "multicast_hops %d failed: %s", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ttl, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto done;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Set the output interface to send the VRRP packet.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (setsockopt(vif->vvi_sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou &vif->vvi_ifindex, sizeof (uint32_t)) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): multicast_if(%d) "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "failed: %s", vr->vvr_conf.vvc_name, vif->vvi_ifindex,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = VRRP_ESYS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v6(%s): multicast_if(%d)"
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou " succeed", vr->vvr_conf.vvc_name, vif->vvi_ifindex);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoudone:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vif->vvi_sockfd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_sockfd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Delete the socket which is used to send VRRP packets. Further, clear
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the IFF_NOACCEPT flag based on the VRRP router's accept mode.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_fini_txsock(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif = vr->vvr_vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_fini_txsock(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vif != NULL) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!vr->vvr_conf.vvc_accept)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_set_noaccept(vr, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) close(vif->vvi_sockfd);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_sockfd = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_vif = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Given the the pseudo header cksum value (sum), caculate the cksum with
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * the rest of VRRP packet.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic uint16_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouin_cksum(int sum, uint16_t plen, void *p)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int nleft;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t *w;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t answer;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t odd_byte = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nleft = plen;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou w = (uint16_t *)p;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (nleft > 1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sum += *w++;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nleft -= 2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* mop up an odd byte, if necessary */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nleft == 1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou *(uchar_t *)(&odd_byte) = *(uchar_t *)w;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sum += odd_byte;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * add back carry outs from top 16 bits to low 16 bits
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sum += (sum >> 16); /* add carry */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou answer = ~sum; /* truncate to 16 bits */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (answer == 0 ? ~0 : answer);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* Pseudo header for v4 */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustruct pshv4 {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in_addr ph4_src;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in_addr ph4_dst;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint8_t ph4_zero; /* always zero */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint8_t ph4_protocol; /* protocol used, IPPROTO_VRRP */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t ph4_len; /* VRRP payload len */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou};
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Checksum routine for VRRP checksum. Note that plen is the upper-layer
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * packet length (in the host byte order), and both IP source and destination
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * addresses are in the network byte order.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic uint16_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_cksum4(struct in_addr *src, struct in_addr *dst, uint16_t plen,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_pkt_t *vp)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct pshv4 ph4;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int nleft;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t *w;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int sum = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph4.ph4_src = *src;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph4.ph4_dst = *dst;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph4.ph4_zero = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph4.ph4_protocol = IPPROTO_VRRP;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph4.ph4_len = htons(plen);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Our algorithm is simple, using a 32 bit accumulator (sum),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * we add sequential 16 bit words to it, and at the end, fold
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * back all the carry bits from the top 16 bits into the lower
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * 16 bits.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nleft = sizeof (struct pshv4);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou w = (uint16_t *)&ph4;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (nleft > 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sum += *w++;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nleft -= 2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (in_cksum(sum, plen, vp));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* Pseudo header for v6 */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustruct pshv6 {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in6_addr ph6_src;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct in6_addr ph6_dst;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint32_t ph6_len; /* VRRP payload len */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint32_t ph6_zero : 24,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph6_protocol : 8; /* protocol used, IPPROTO_VRRP */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou};
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Checksum routine for VRRP checksum. Note that plen is the upper-layer
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * packet length (in the host byte order), and both IP source and destination
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * addresses are in the network byte order.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic uint16_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_cksum6(struct in6_addr *src, struct in6_addr *dst, uint16_t plen,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_pkt_t *vp)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct pshv6 ph6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int nleft;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint16_t *w;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int sum = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph6.ph6_src = *src;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph6.ph6_dst = *dst;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph6.ph6_zero = 0;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph6.ph6_protocol = IPPROTO_VRRP;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ph6.ph6_len = htonl((uint32_t)plen);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Our algorithm is simple, using a 32 bit accumulator (sum),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * we add sequential 16 bit words to it, and at the end, fold
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * back all the carry bits from the top 16 bits into the lower
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * 16 bits.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nleft = sizeof (struct pshv6);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou w = (uint16_t *)&ph6;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou while (nleft > 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sum += *w++;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nleft -= 2;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (in_cksum(sum, plen, vp));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_state_i2m(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_i2m(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_INIT, VRRP_STATE_MASTER, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_send_adv(vr, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = vr->vvr_conf.vvc_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout, vrrp_adv_timeout, vr)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_state_i2m(): unable to start timer");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_i2m(%s): start "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "vrrp_adv_timeout(%d)", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_state_i2b(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_i2b(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_INIT, VRRP_STATE_BACKUP, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Reinitialize the Master advertisement interval to be the configured
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * value.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_err = VRRP_SUCCESS;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_master_adver_int = vr->vvr_conf.vvc_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout, vrrp_b2m_timeout, vr)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_state_i2b(): unable to set timer");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_i2b(%s): start "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "vrrp_b2m_timeout(%d)", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvoid
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_state_m2i(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_m2i(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_MASTER, VRRP_STATE_INIT, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_virtualip_update(vr, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bzero(&vr->vvr_peer, sizeof (vrrp_peer_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_cancel_timer(vrrpd_timerq, vr->vvr_timer_id, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvoid
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_state_b2i(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_b2i(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou bzero(&vr->vvr_peer, sizeof (vrrp_peer_t));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_cancel_timer(vrrpd_timerq, vr->vvr_timer_id, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_BACKUP, VRRP_STATE_INIT, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_virtualip_update(vr, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* ARGSUSED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_b2m_timeout(iu_tq_t *tq, void *arg)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr = (vrrp_vr_t *)arg;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrp_b2m_timeout(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_state_b2m(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/* ARGSUSED */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_adv_timeout(iu_tq_t *tq, void *arg)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_vr_t *vr = (vrrp_vr_t *)arg;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrp_adv_timeout(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_send_adv(vr, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout, vrrp_adv_timeout, vr)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrp_adv_timeout(%s): start timer failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrp_adv_timeout(%s): start "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "vrrp_adv_timeout(%d)", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_state_b2m(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_b2m(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_BACKUP, VRRP_STATE_MASTER, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_send_adv(vr, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = vr->vvr_conf.vvc_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout, vrrp_adv_timeout, vr)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_state_b2m(%s): start timer failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_b2m(%s): start "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "vrrp_adv_timeout(%d)", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_state_m2b(vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_m2b(%s)", vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_state_trans(VRRP_STATE_MASTER, VRRP_STATE_BACKUP, vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (err);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Cancel the adver_timer.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_master_adver_int = vr->vvr_peer_adver_int;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) iu_cancel_timer(vrrpd_timerq, vr->vvr_timer_id, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout, vrrp_b2m_timeout, vr)) == -1) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_state_m2b(%s): start timer failed",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_m2b(%s) start "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "vrrp_b2m_timeout(%d)", vr->vvr_conf.vvc_name,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_timeout);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Set the IFF_NOACCESS flag on the VNIC interface of the VRRP router
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * based on its access mode.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_set_noaccept(vrrp_vr_t *vr, boolean_t on)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif = vr->vvr_vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t curr_flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct lifreq lifr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int s;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_set_noaccept(%s, %s)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, on ? "on" : "off");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * Possibly no virtual address exists on this VRRP router yet.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vif == NULL)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_set_noaccept(%s, %s)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_ifname, vrrp_state2str(vr->vvr_state));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou s = (vif->vvi_af == AF_INET) ? vrrpd_ctlsock_fd : vrrpd_ctlsock6_fd;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strncpy(lifr.lifr_name, vif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (lifr.lifr_name));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (errno != ENXIO && errno != ENOENT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_set_noaccept(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "SIOCGLIFFLAGS on %s failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_ifname, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou curr_flags = lifr.lifr_flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (on)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou lifr.lifr_flags |= IFF_NOACCEPT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou lifr.lifr_flags &= ~IFF_NOACCEPT;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (lifr.lifr_flags != curr_flags) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (errno != ENXIO && errno != ENOENT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_set_noaccept(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "SIOCSLIFFLAGS 0x%llx on %s failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou on ? "no_accept" : "accept",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou lifr.lifr_flags, vif->vvi_ifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_virtualip_updateone(vrrp_intf_t *vif, vrrp_ip_t *ip, boolean_t checkonly)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_state_t state = vif->vvi_vr_state;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct lifreq lifr;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int af = vif->vvi_af;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou uint64_t curr_flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int s;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(IS_VIRTUAL_INTF(vif));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(af, &ip->vip_addr, abuf, INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_virtualip_updateone(%s, %s%s)",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_ifname, abuf, checkonly ? ", checkonly" : "");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou s = (af == AF_INET) ? vrrpd_ctlsock_fd : vrrpd_ctlsock6_fd;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) strncpy(lifr.lifr_name, ip->vip_lifname,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sizeof (lifr.lifr_name));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (errno != ENXIO && errno != ENOENT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_virtualip_updateone(%s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "SIOCGLIFFLAGS on %s/%s failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_ifname, lifr.lifr_name, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou curr_flags = lifr.lifr_flags;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (state == VRRP_STATE_MASTER)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou lifr.lifr_flags |= IFF_UP;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou else
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou lifr.lifr_flags &= ~IFF_UP;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (lifr.lifr_flags == curr_flags)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (checkonly) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "VRRP virtual IP %s/%s was brought %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_lifname, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou state == VRRP_STATE_MASTER ? "down" : "up");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou } else if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (errno != ENXIO && errno != ENOENT) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_virtualip_updateone(%s, %s): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "bring %s %s/%s failed: %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_ifname, vrrp_state2str(state),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou state == VRRP_STATE_MASTER ? "up" : "down",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou ip->vip_lifname, abuf, strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ESYS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic vrrp_err_t
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_virtualip_update(vrrp_vr_t *vr, boolean_t checkonly)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_state_t state;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_intf_t *vif = vr->vvr_vif;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_ip_t *ip, *nextip;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou char abuf[INET6_ADDRSTRLEN];
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_err_t err;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_virtualip_update(%s, %s, %s)%s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, vrrp_state2str(vr->vvr_state),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_ifname, checkonly ? " checkonly" : "");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou state = vr->vvr_state;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vif != NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(IS_VIRTUAL_INTF(vif));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vif->vvi_vr_state != state);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vif->vvi_vr_state = state;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou for (ip = TAILQ_FIRST(&vif->vvi_iplist); ip != NULL; ip = nextip) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nextip = TAILQ_NEXT(ip, vip_next);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou err = vrrpd_virtualip_updateone(vif, ip, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!checkonly && err != VRRP_SUCCESS) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED E_CONSTANT_CONDITION */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRPADDR2STR(vif->vvi_af, &ip->vip_addr, abuf,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou INET6_ADDRSTRLEN, _B_FALSE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_virtualip_update() update "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "%s over %s failed", abuf, vif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_ip(vif, ip);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * The IP address is deleted when it is failed to be brought
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * up. If no IP addresses are left, delete this interface.
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (!checkonly && TAILQ_EMPTY(&vif->vvi_iplist)) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG0, "vrrpd_virtualip_update(): "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "no IP left over %s", vif->vvi_ifname);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrpd_delete_if(vif, _B_TRUE);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_ENOVIRT);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (VRRP_SUCCESS);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvoid
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_state_trans(vrrp_state_t prev_s, vrrp_state_t s, vrrp_vr_t *vr)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_DBG1, "vrrpd_state_trans(%s): %s --> %s",
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_conf.vvc_name, vrrp_state2str(prev_s), vrrp_state2str(s));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou assert(vr->vvr_state == prev_s);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_state = s;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vr->vvr_prev_state = prev_s;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) gettimeofday(&vr->vvr_st_time, NULL);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vrrpd_post_event(vr->vvr_conf.vvc_name, prev_s, s);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrpd_post_event(const char *name, vrrp_state_t prev_st, vrrp_state_t st)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou sysevent_id_t eid;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nvlist_t *nvl = NULL;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * sysevent is not supported in the non-global zone
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (getzoneid() != GLOBAL_ZONEID)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto failed;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nvlist_add_uint8(nvl, VRRP_EVENT_VERSION,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou VRRP_EVENT_CUR_VERSION) != 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto failed;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nvlist_add_string(nvl, VRRP_EVENT_ROUTER_NAME, name) != 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto failed;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nvlist_add_uint8(nvl, VRRP_EVENT_STATE, st) != 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto failed;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (nvlist_add_uint8(nvl, VRRP_EVENT_PREV_STATE, prev_st) != 0)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou goto failed;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (sysevent_post_event(EC_VRRP, ESC_VRRP_STATE_CHANGE,
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou SUNW_VENDOR, VRRP_EVENT_PUBLISHER, nvl, &eid) == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou nvlist_free(nvl);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (0);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoufailed:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_log(VRRP_ERR, "vrrpd_post_event(): `state change (%s --> %s)' "
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou "sysevent posting failed: %s", vrrp_state2str(prev_st),
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou vrrp_state2str(st), strerror(errno));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(nvl);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (-1);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * timeval processing functions
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic int
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutimeval_to_milli(struct timeval tv)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return ((int)(tv.tv_sec * 1000 + tv.tv_usec / 1000 + 0.5));
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic struct timeval
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoutimeval_delta(struct timeval t1, struct timeval t2)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou struct timeval t;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou t.tv_sec = t1.tv_sec - t2.tv_sec;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou t.tv_usec = t1.tv_usec - t2.tv_usec;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (t.tv_usec < 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou t.tv_usec += 1000000;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou t.tv_sec--;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return (t);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou/*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * print error messages to the terminal or to syslog
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhoustatic void
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhouvrrp_log(int level, char *message, ...)
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou{
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou va_list ap;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou int log_level = -1;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou va_start(ap, message);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (vrrp_logflag == 0) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou if (level <= vrrp_debug_level) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * VRRP_ERR goes to stderr, others go to stdout
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou FILE *out = (level <= VRRP_ERR) ? stderr : stdout;
c5e0ece05310eec3c585344bcff875855f3f507aCathy Zhou (void) fprintf(out, "vrrpd: ");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED: E_SEC_PRINTF_VAR_FMT */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vfprintf(out, message, ap);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) fprintf(out, "\n");
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) fflush(out);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou va_end(ap);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou return;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou * translate VRRP_* to LOG_*
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou switch (level) {
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case VRRP_ERR:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou log_level = LOG_ERR;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case VRRP_WARNING:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou log_level = LOG_WARNING;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case VRRP_NOTICE:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou log_level = LOG_NOTICE;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou case VRRP_DBG0:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou log_level = LOG_INFO;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou default:
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou log_level = LOG_DEBUG;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou break;
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou }
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou /* LINTED: E_SEC_PRINTF_VAR_FMT */
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou (void) vsyslog(log_level, message, ap);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou va_end(ap);
1cb875ae88fb9463b368e725c2444776595895cbCathy Zhou}