1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  28  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/socket.h>
  33 #include <sys/sockio.h>
  34 #include <sys/sysevent/vrrp.h>
  35 #include <sys/sysevent/eventdefs.h>
  36 #include <sys/varargs.h>
  37 #include <auth_attr.h>
  38 #include <ctype.h>
  39 #include <fcntl.h>
  40 #include <stdlib.h>
  41 #include <strings.h>
  42 #include <errno.h>
  43 #include <unistd.h>
  44 #include <zone.h>
  45 #include <libsysevent.h>
  46 #include <limits.h>
  47 #include <locale.h>
  48 #include <arpa/inet.h>
  49 #include <signal.h>
  50 #include <assert.h>
  51 #include <ucred.h>
  52 #include <bsm/adt.h>
  53 #include <bsm/adt_event.h>
  54 #include <priv_utils.h>
  55 #include <libdllink.h>
  56 #include <libdlvnic.h>
  57 #include <libipadm.h>
  58 #include <pwd.h>
  59 #include <libvrrpadm.h>
  60 #include <net/route.h>
  61 #include "vrrpd_impl.h"
  62 
  63 /*
  64  * A VRRP router can be only start participating the VRRP protocol of a virtual
  65  * router when all the following conditions are met:
  66  *
  67  * - The VRRP router is enabled (vr->vvr_conf.vvc_enabled is _B_TRUE)
  68  * - The RX socket is successfully created over the physical interface to
  69  *   receive the VRRP multicast advertisement. Note that one RX socket can
  70  *   be shared by several VRRP routers configured over the same physical
  71  *   interface. (See vrrpd_init_rxsock())
  72  * - The TX socket is successfully created over the VNIC interface to send
  73  *   the VRRP advertisment. (See vrrpd_init_txsock())
  74  * - The primary IP address has been successfully selected over the physical
  75  *   interface. (See vrrpd_select_primary())
  76  *
  77  * If a VRRP router is enabled but the other conditions haven't be satisfied,
  78  * the router will be stay at the VRRP_STATE_INIT state. If all the above
  79  * conditions are met, the VRRP router will be transit to either
  80  * the VRRP_STATE_MASTER or the VRRP_STATE_BACKUP state, depends on the VRRP
  81  * protocol.
  82  */
  83 
  84 #define skip_whitespace(p)      while (isspace(*(p))) ++(p)
  85 
  86 #define BUFFSIZE        65536
  87 
  88 #define MAXLINELEN      1024
  89 
  90 #define VRRPCONF        "/etc/inet/vrrp.conf"
  91 
  92 typedef struct vrrpd_rtsock_s {
  93         int             vrt_af;         /* address family */
  94         int             vrt_fd;         /* socket for the PF_ROUTE msg */
  95         iu_event_id_t   vrt_eid;        /* event ID */
  96 } vrrpd_rtsock_t;
  97 
  98 static ipadm_handle_t   vrrp_ipadm_handle = NULL;       /* libipadm handle */
  99 static int              vrrp_logflag = 0;
 100 boolean_t               vrrp_debug_level = 0;
 101 iu_eh_t                 *vrrpd_eh = NULL;
 102 iu_tq_t                 *vrrpd_timerq = NULL;
 103 static vrrp_handle_t    vrrpd_vh = NULL;
 104 static int              vrrpd_cmdsock_fd = -1;  /* socket to communicate */
 105                                                 /* between vrrpd/libvrrpadm */
 106 static iu_event_id_t    vrrpd_cmdsock_eid = -1;
 107 static int              vrrpd_ctlsock_fd = -1;  /* socket to bring up/down */
 108                                                 /* the virtual IP addresses */
 109 static int              vrrpd_ctlsock6_fd = -1;
 110 static vrrpd_rtsock_t   vrrpd_rtsocks[2] = {
 111         {AF_INET, -1, -1},
 112         {AF_INET6, -1, -1}
 113 };
 114 static iu_timer_id_t    vrrp_scan_timer_id = -1;
 115 
 116 TAILQ_HEAD(vrrp_vr_list_s, vrrp_vr_s);
 117 TAILQ_HEAD(vrrp_intf_list_s, vrrp_intf_s);
 118 static struct vrrp_vr_list_s    vrrp_vr_list;
 119 static struct vrrp_intf_list_s  vrrp_intf_list;
 120 static char             vrrpd_conffile[MAXPATHLEN];
 121 
 122 /*
 123  * Multicast address of VRRP advertisement in network byte order
 124  */
 125 static vrrp_addr_t      vrrp_muladdr4;
 126 static vrrp_addr_t      vrrp_muladdr6;
 127 
 128 static int              vrrpd_scan_interval = 20000;    /* ms */
 129 static int              pfds[2];
 130 
 131 /*
 132  * macros to calculate skew_time and master_down_timer
 133  *
 134  * Note that the input is in centisecs and output are in msecs
 135  */
 136 #define SKEW_TIME(pri, intv)    ((intv) * (256 - (pri)) / 256)
 137 #define MASTER_DOWN_INTERVAL(pri, intv) (3 * (intv) + SKEW_TIME((pri), (intv)))
 138 
 139 #define SKEW_TIME_VR(vr)        \
 140         SKEW_TIME((vr)->vvr_conf.vvc_pri, (vr)->vvr_master_adver_int)
 141 #define MASTER_DOWN_INTERVAL_VR(vr)     \
 142         MASTER_DOWN_INTERVAL((vr)->vvr_conf.vvc_pri, (vr)->vvr_master_adver_int)
 143 
 144 #define VRRP_CONF_UPDATE        0x01
 145 #define VRRP_CONF_DELETE        0x02
 146 
 147 static char *af_str(int);
 148 
 149 static iu_tq_callback_t vrrp_adv_timeout;
 150 static iu_tq_callback_t vrrp_b2m_timeout;
 151 static iu_eh_callback_t vrrpd_sock_handler;
 152 static iu_eh_callback_t vrrpd_rtsock_handler;
 153 static iu_eh_callback_t vrrpd_cmdsock_handler;
 154 
 155 static int daemon_init();
 156 
 157 static vrrp_err_t vrrpd_init();
 158 static void vrrpd_fini();
 159 static vrrp_err_t vrrpd_cmdsock_create();
 160 static void vrrpd_cmdsock_destroy();
 161 static vrrp_err_t vrrpd_rtsock_create();
 162 static void vrrpd_rtsock_destroy();
 163 static vrrp_err_t vrrpd_ctlsock_create();
 164 static void vrrpd_ctlsock_destroy();
 165 
 166 static void vrrpd_scan_timer(iu_tq_t *, void *);
 167 static void vrrpd_scan(int);
 168 static vrrp_err_t vrrpd_init_rxsock(vrrp_vr_t *);
 169 static void vrrpd_fini_rxsock(vrrp_vr_t *);
 170 static vrrp_err_t vrrpd_init_txsock(vrrp_vr_t *);
 171 static vrrp_err_t vrrpd_init_txsock_v4(vrrp_vr_t *);
 172 static vrrp_err_t vrrpd_init_txsock_v6(vrrp_vr_t *);
 173 static void vrrpd_fini_txsock(vrrp_vr_t *);
 174 
 175 static vrrp_err_t vrrpd_create_vr(vrrp_vr_conf_t *);
 176 static vrrp_err_t vrrpd_enable_vr(vrrp_vr_t *);
 177 static void vrrpd_disable_vr(vrrp_vr_t *, vrrp_intf_t *, boolean_t);
 178 static void vrrpd_delete_vr(vrrp_vr_t *);
 179 
 180 static vrrp_err_t vrrpd_create(vrrp_vr_conf_t *, boolean_t);
 181 static vrrp_err_t vrrpd_delete(const char *);
 182 static vrrp_err_t vrrpd_enable(const char *, boolean_t);
 183 static vrrp_err_t vrrpd_disable(const char *);
 184 static vrrp_err_t vrrpd_modify(vrrp_vr_conf_t *, uint32_t);
 185 static void vrrpd_list(vrid_t, char *, int, vrrp_ret_list_t *, size_t *);
 186 static void vrrpd_query(const char *, vrrp_ret_query_t *, size_t *);
 187 
 188 static boolean_t vrrp_rd_prop_name(vrrp_vr_conf_t *, const char *);
 189 static boolean_t vrrp_rd_prop_vrid(vrrp_vr_conf_t *, const char *);
 190 static boolean_t vrrp_rd_prop_af(vrrp_vr_conf_t *, const char *);
 191 static boolean_t vrrp_rd_prop_pri(vrrp_vr_conf_t *, const char *);
 192 static boolean_t vrrp_rd_prop_adver_int(vrrp_vr_conf_t *, const char *);
 193 static boolean_t vrrp_rd_prop_preempt(vrrp_vr_conf_t *, const char *);
 194 static boolean_t vrrp_rd_prop_accept(vrrp_vr_conf_t *, const char *);
 195 static boolean_t vrrp_rd_prop_ifname(vrrp_vr_conf_t *, const char *);
 196 static boolean_t vrrp_rd_prop_enabled(vrrp_vr_conf_t *, const char *);
 197 static int vrrp_wt_prop_name(vrrp_vr_conf_t *, char *, size_t);
 198 static int vrrp_wt_prop_vrid(vrrp_vr_conf_t *, char *, size_t);
 199 static int vrrp_wt_prop_af(vrrp_vr_conf_t *, char *, size_t);
 200 static int vrrp_wt_prop_pri(vrrp_vr_conf_t *, char *, size_t);
 201 static int vrrp_wt_prop_adver_int(vrrp_vr_conf_t *, char *, size_t);
 202 static int vrrp_wt_prop_preempt(vrrp_vr_conf_t *, char *, size_t);
 203 static int vrrp_wt_prop_accept(vrrp_vr_conf_t *, char *, size_t);
 204 static int vrrp_wt_prop_ifname(vrrp_vr_conf_t *, char *, size_t);
 205 static int vrrp_wt_prop_enabled(vrrp_vr_conf_t *, char *, size_t);
 206 
 207 static void vrrpd_cmd_create(void *, void *, size_t *);
 208 static void vrrpd_cmd_delete(void *, void *, size_t *);
 209 static void vrrpd_cmd_enable(void *, void *, size_t *);
 210 static void vrrpd_cmd_disable(void *, void *, size_t *);
 211 static void vrrpd_cmd_modify(void *, void *, size_t *);
 212 static void vrrpd_cmd_list(void *, void *, size_t *);
 213 static void vrrpd_cmd_query(void *, void *, size_t *);
 214 
 215 static vrrp_vr_t *vrrpd_lookup_vr_by_vrid(char *, vrid_t vrid_t, int);
 216 static vrrp_vr_t *vrrpd_lookup_vr_by_name(const char *);
 217 static vrrp_intf_t *vrrpd_lookup_if(const char *, int);
 218 static vrrp_err_t vrrpd_create_if(const char *, int, uint32_t, vrrp_intf_t **);
 219 static void vrrpd_delete_if(vrrp_intf_t *, boolean_t);
 220 static vrrp_err_t vrrpd_create_ip(vrrp_intf_t *, const char *, vrrp_addr_t *,
 221     uint64_t flags);
 222 static void vrrpd_delete_ip(vrrp_intf_t *, vrrp_ip_t *);
 223 
 224 static void vrrpd_init_ipcache(int);
 225 static void vrrpd_update_ipcache(int);
 226 static ipadm_status_t vrrpd_walk_addr_info(int);
 227 static vrrp_err_t vrrpd_add_ipaddr(char *, int, vrrp_addr_t *,
 228     int, uint64_t);
 229 static vrrp_ip_t *vrrpd_select_primary(vrrp_intf_t *);
 230 static void vrrpd_reselect_primary(vrrp_intf_t *);
 231 static void vrrpd_reenable_all_vr();
 232 static void vrrpd_remove_if(vrrp_intf_t *, boolean_t);
 233 
 234 static uint16_t in_cksum(int, uint16_t, void *);
 235 static uint16_t vrrp_cksum4(struct in_addr *, struct in_addr *,
 236     uint16_t, vrrp_pkt_t *);
 237 static uint16_t vrrp_cksum6(struct in6_addr *, struct in6_addr *,
 238     uint16_t, vrrp_pkt_t *);
 239 static size_t vrrpd_build_vrrp(vrrp_vr_t *, uchar_t *, int, boolean_t);
 240 
 241 static void vrrpd_process_adv(vrrp_vr_t *, vrrp_addr_t *, vrrp_pkt_t *);
 242 static vrrp_err_t vrrpd_send_adv(vrrp_vr_t *, boolean_t);
 243 
 244 /* state transition functions */
 245 static vrrp_err_t vrrpd_state_i2m(vrrp_vr_t *);
 246 static vrrp_err_t vrrpd_state_i2b(vrrp_vr_t *);
 247 static void vrrpd_state_m2i(vrrp_vr_t *);
 248 static void vrrpd_state_b2i(vrrp_vr_t *);
 249 static vrrp_err_t vrrpd_state_b2m(vrrp_vr_t *);
 250 static vrrp_err_t vrrpd_state_m2b(vrrp_vr_t *);
 251 static void vrrpd_state_trans(vrrp_state_t, vrrp_state_t, vrrp_vr_t *);
 252 
 253 static vrrp_err_t vrrpd_set_noaccept(vrrp_vr_t *, boolean_t);
 254 static vrrp_err_t vrrpd_virtualip_update(vrrp_vr_t *, boolean_t);
 255 static vrrp_err_t vrrpd_virtualip_updateone(vrrp_intf_t *, vrrp_ip_t *,
 256     boolean_t);
 257 static int vrrpd_post_event(const char *, vrrp_state_t, vrrp_state_t);
 258 
 259 static void vrrpd_initconf();
 260 static vrrp_err_t vrrpd_updateconf(vrrp_vr_conf_t *, uint_t);
 261 static vrrp_err_t vrrpd_write_vrconf(char *, size_t, vrrp_vr_conf_t *);
 262 static vrrp_err_t vrrpd_read_vrconf(char *, vrrp_vr_conf_t *);
 263 static vrrp_err_t vrrpd_readprop(const char *, vrrp_vr_conf_t *);
 264 static void vrrpd_cleanup();
 265 
 266 static void vrrp_log(int, char *, ...);
 267 static int timeval_to_milli(struct timeval);
 268 static struct timeval timeval_delta(struct timeval, struct timeval);
 269 
 270 typedef struct vrrpd_prop_s {
 271         char            *vs_propname;
 272         boolean_t       (*vs_propread)(vrrp_vr_conf_t *, const char *);
 273         int             (*vs_propwrite)(vrrp_vr_conf_t *, char *, size_t);
 274 } vrrp_prop_t;
 275 
 276 /*
 277  * persistent VRRP properties array
 278  */
 279 static vrrp_prop_t vrrp_prop_info_tbl[] = {
 280         {"name", vrrp_rd_prop_name, vrrp_wt_prop_name},
 281         {"vrid", vrrp_rd_prop_vrid, vrrp_wt_prop_vrid},
 282         {"priority", vrrp_rd_prop_pri, vrrp_wt_prop_pri},
 283         {"adv_intval", vrrp_rd_prop_adver_int, vrrp_wt_prop_adver_int},
 284         {"preempt_mode", vrrp_rd_prop_preempt, vrrp_wt_prop_preempt},
 285         {"accept_mode", vrrp_rd_prop_accept, vrrp_wt_prop_accept},
 286         {"interface", vrrp_rd_prop_ifname, vrrp_wt_prop_ifname},
 287         {"af", vrrp_rd_prop_af, vrrp_wt_prop_af},
 288         {"enabled", vrrp_rd_prop_enabled, vrrp_wt_prop_enabled}
 289 };
 290 
 291 #define VRRP_PROP_INFO_TABSIZE  \
 292         (sizeof (vrrp_prop_info_tbl) / sizeof (vrrp_prop_t))
 293 
 294 typedef void vrrp_cmd_func_t(void *, void *, size_t *);
 295 
 296 typedef struct vrrp_cmd_info_s {
 297         vrrp_cmd_type_t vi_cmd;
 298         size_t          vi_reqsize;
 299         size_t          vi_acksize;     /* 0 if the size is variable */
 300         boolean_t       vi_setop;       /* Set operation? Check credentials */
 301         vrrp_cmd_func_t *vi_cmdfunc;
 302 } vrrp_cmd_info_t;
 303 
 304 static vrrp_cmd_info_t vrrp_cmd_info_tbl[] = {
 305         {VRRP_CMD_CREATE, sizeof (vrrp_cmd_create_t),
 306             sizeof (vrrp_ret_create_t), _B_TRUE, vrrpd_cmd_create},
 307         {VRRP_CMD_DELETE, sizeof (vrrp_cmd_delete_t),
 308             sizeof (vrrp_ret_delete_t), _B_TRUE, vrrpd_cmd_delete},
 309         {VRRP_CMD_ENABLE, sizeof (vrrp_cmd_enable_t),
 310             sizeof (vrrp_ret_enable_t), _B_TRUE, vrrpd_cmd_enable},
 311         {VRRP_CMD_DISABLE, sizeof (vrrp_cmd_disable_t),
 312             sizeof (vrrp_ret_disable_t), _B_TRUE, vrrpd_cmd_disable},
 313         {VRRP_CMD_MODIFY, sizeof (vrrp_cmd_modify_t),
 314             sizeof (vrrp_ret_modify_t), _B_TRUE, vrrpd_cmd_modify},
 315         {VRRP_CMD_QUERY, sizeof (vrrp_cmd_query_t), 0,
 316             _B_FALSE, vrrpd_cmd_query},
 317         {VRRP_CMD_LIST, sizeof (vrrp_cmd_list_t), 0,
 318             _B_FALSE, vrrpd_cmd_list}
 319 };
 320 
 321 #define VRRP_DOOR_INFO_TABLE_SIZE       \
 322         (sizeof (vrrp_cmd_info_tbl) / sizeof (vrrp_cmd_info_t))
 323 
 324 static int
 325 ipaddr_cmp(int af, vrrp_addr_t *addr1, vrrp_addr_t *addr2)
 326 {
 327         if (af == AF_INET) {
 328                 return (memcmp(&addr1->in4.sin_addr,
 329                     &addr2->in4.sin_addr, sizeof (struct in_addr)));
 330         } else {
 331                 return (memcmp(&addr1->in6.sin6_addr,
 332                     &addr2->in6.sin6_addr, sizeof (struct in6_addr)));
 333         }
 334 }
 335 
 336 static vrrp_vr_t *
 337 vrrpd_lookup_vr_by_vrid(char *ifname, vrid_t vrid, int af)
 338 {
 339         vrrp_vr_t *vr;
 340 
 341         TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
 342                 if (strcmp(vr->vvr_conf.vvc_link, ifname) == 0 &&
 343                     vr->vvr_conf.vvc_vrid == vrid &&
 344                     vr->vvr_conf.vvc_af == af) {
 345                         break;
 346                 }
 347         }
 348         return (vr);
 349 }
 350 
 351 static vrrp_vr_t *
 352 vrrpd_lookup_vr_by_name(const char *name)
 353 {
 354         vrrp_vr_t *vr;
 355 
 356         TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
 357                 if (strcmp(vr->vvr_conf.vvc_name, name) == 0)
 358                         break;
 359         }
 360         return (vr);
 361 }
 362 
 363 static vrrp_intf_t *
 364 vrrpd_lookup_if(const char *ifname, int af)
 365 {
 366         vrrp_intf_t     *intf;
 367 
 368         TAILQ_FOREACH(intf, &vrrp_intf_list, vvi_next) {
 369                 if (strcmp(ifname, intf->vvi_ifname) == 0 &&
 370                     af == intf->vvi_af) {
 371                         break;
 372                 }
 373         }
 374         return (intf);
 375 }
 376 
 377 static vrrp_err_t
 378 vrrpd_create_if(const char *ifname, int af, uint32_t ifindex,
 379     vrrp_intf_t **intfp)
 380 {
 381         vrrp_intf_t     *intf;
 382 
 383         vrrp_log(VRRP_DBG0, "vrrpd_create_if(%s, %s, %d)",
 384             ifname, af_str(af), ifindex);
 385 
 386         if (((*intfp) = malloc(sizeof (vrrp_intf_t))) == NULL) {
 387                 vrrp_log(VRRP_ERR, "vrrpd_create_if(): failed to "
 388                     "allocate %s/%s interface", ifname, af_str(af));
 389                 return (VRRP_ENOMEM);
 390         }
 391 
 392         intf = *intfp;
 393         TAILQ_INIT(&intf->vvi_iplist);
 394         (void) strlcpy(intf->vvi_ifname, ifname, sizeof (intf->vvi_ifname));
 395         intf->vvi_af = af;
 396         intf->vvi_sockfd = -1;
 397         intf->vvi_nvr = 0;
 398         intf->vvi_eid = -1;
 399         intf->vvi_pip = NULL;
 400         intf->vvi_ifindex = ifindex;
 401         intf->vvi_state = NODE_STATE_NEW;
 402         intf->vvi_vr_state = VRRP_STATE_INIT;
 403         TAILQ_INSERT_TAIL(&vrrp_intf_list, intf, vvi_next);
 404         return (VRRP_SUCCESS);
 405 }
 406 
 407 /*
 408  * An interface is deleted. If update_vr is true, the deletion of the interface
 409  * may cause the state transition of assoicated VRRP router (if this interface
 410  * is either the primary or the VNIC interface of the VRRP router); otherwise,
 411  * simply delete the interface without updating the VRRP router.
 412  */
 413 static void
 414 vrrpd_delete_if(vrrp_intf_t *intf, boolean_t update_vr)
 415 {
 416         vrrp_ip_t       *ip;
 417 
 418         vrrp_log(VRRP_DBG0, "vrrpd_delete_if(%s, %s, %supdate_vr)",
 419             intf->vvi_ifname, af_str(intf->vvi_af), update_vr ? "" : "no_");
 420 
 421         if (update_vr) {
 422                 /*
 423                  * If a this interface is the physical interface or the VNIC
 424                  * of a VRRP router, the deletion of the interface (no IP
 425                  * address exists on this interface) may cause the state
 426                  * transition of the VRRP router. call vrrpd_remove_if()
 427                  * to find all corresponding VRRP router and update their
 428                  * states.
 429                  */
 430                 vrrpd_remove_if(intf, _B_FALSE);
 431         }
 432 
 433         /*
 434          * First remove and delete all the IP addresses on the interface
 435          */
 436         while (!TAILQ_EMPTY(&intf->vvi_iplist)) {
 437                 ip = TAILQ_FIRST(&intf->vvi_iplist);
 438                 vrrpd_delete_ip(intf, ip);
 439         }
 440 
 441         /*
 442          * Then remove and delete the interface
 443          */
 444         TAILQ_REMOVE(&vrrp_intf_list, intf, vvi_next);
 445         (void) free(intf);
 446 }
 447 
 448 static vrrp_err_t
 449 vrrpd_create_ip(vrrp_intf_t *intf, const char *lifname, vrrp_addr_t *addr,
 450     uint64_t flags)
 451 {
 452         vrrp_ip_t       *ip;
 453         char            abuf[INET6_ADDRSTRLEN];
 454 
 455         /* LINTED E_CONSTANT_CONDITION */
 456         VRRPADDR2STR(intf->vvi_af, addr, abuf, INET6_ADDRSTRLEN, _B_FALSE);
 457         vrrp_log(VRRP_DBG0, "vrrpd_create_ip(%s, %s, %s, 0x%x)",
 458             intf->vvi_ifname, lifname, abuf, flags);
 459 
 460         if ((ip = malloc(sizeof (vrrp_ip_t))) == NULL) {
 461                 vrrp_log(VRRP_ERR, "vrrpd_create_ip(%s, %s):"
 462                     "failed to allocate IP", lifname, abuf);
 463                 return (VRRP_ENOMEM);
 464         }
 465 
 466         (void) strncpy(ip->vip_lifname, lifname, sizeof (ip->vip_lifname));
 467         ip->vip_state = NODE_STATE_NEW;
 468         ip->vip_flags = flags;
 469         (void) memcpy(&ip->vip_addr, addr, sizeof (ip->vip_addr));
 470 
 471         /*
 472          * Make sure link-local IPv6 IP addresses are at the head of the list
 473          */
 474         if (intf->vvi_af == AF_INET6 &&
 475             IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr)) {
 476                 TAILQ_INSERT_HEAD(&intf->vvi_iplist, ip, vip_next);
 477         } else {
 478                 TAILQ_INSERT_TAIL(&intf->vvi_iplist, ip, vip_next);
 479         }
 480         return (VRRP_SUCCESS);
 481 }
 482 
 483 static void
 484 vrrpd_delete_ip(vrrp_intf_t *intf, vrrp_ip_t *ip)
 485 {
 486         char    abuf[INET6_ADDRSTRLEN];
 487         int     af = intf->vvi_af;
 488 
 489         /* LINTED E_CONSTANT_CONDITION */
 490         VRRPADDR2STR(af, &ip->vip_addr, abuf, sizeof (abuf), _B_FALSE);
 491         vrrp_log(VRRP_DBG0, "vrrpd_delete_ip(%s, %s, %s) is %sprimary",
 492             intf->vvi_ifname, ip->vip_lifname, abuf,
 493             intf->vvi_pip == ip ? "" : "not ");
 494 
 495         if (intf->vvi_pip == ip)
 496                 intf->vvi_pip = NULL;
 497 
 498         TAILQ_REMOVE(&intf->vvi_iplist, ip, vip_next);
 499         (void) free(ip);
 500 }
 501 
 502 static char *
 503 rtm_event2str(uchar_t event)
 504 {
 505         switch (event) {
 506         case RTM_NEWADDR:
 507                 return ("RTM_NEWADDR");
 508         case RTM_DELADDR:
 509                 return ("RTM_DELADDR");
 510         case RTM_IFINFO:
 511                 return ("RTM_IFINFO");
 512         case RTM_ADD:
 513                 return ("RTM_ADD");
 514         case RTM_DELETE:
 515                 return ("RTM_DELETE");
 516         case RTM_CHANGE:
 517                 return ("RTM_CHANGE");
 518         case RTM_OLDADD:
 519                 return ("RTM_OLDADD");
 520         case RTM_OLDDEL:
 521                 return ("RTM_OLDDEL");
 522         case RTM_CHGADDR:
 523                 return ("RTM_CHGADDR");
 524         case RTM_FREEADDR:
 525                 return ("RTM_FREEADDR");
 526         default:
 527                 return ("RTM_OTHER");
 528         }
 529 }
 530 
 531 /*
 532  * This is called by the child process to inform the parent process to
 533  * exit with the given return value. Note that the child process
 534  * (the daemon process) informs the parent process to exit when anything
 535  * goes wrong or when all the intialization is done.
 536  */
 537 static int
 538 vrrpd_inform_parent_exit(int rv)
 539 {
 540         int err = 0;
 541 
 542         /*
 543          * If vrrp_debug_level is none-zero, vrrpd is not running as
 544          * a daemon. Return directly.
 545          */
 546         if (vrrp_debug_level != 0)
 547                 return (0);
 548 
 549         if (write(pfds[1], &rv, sizeof (int)) != sizeof (int)) {
 550                 err = errno;
 551                 (void) close(pfds[1]);
 552                 return (err);
 553         }
 554         (void) close(pfds[1]);
 555         return (0);
 556 }
 557 
 558 int
 559 main(int argc, char *argv[])
 560 {
 561         int c, err;
 562         struct sigaction sa;
 563         sigset_t mask;
 564         struct rlimit rl;
 565 
 566         (void) setlocale(LC_ALL, "");
 567         (void) textdomain(TEXT_DOMAIN);
 568 
 569         /*
 570          * We need PRIV_SYS_CONFIG to post VRRP sysevent, PRIV_NET_RAWACESS
 571          * and PRIV_NET_ICMPACCESS to open  the raw socket, PRIV_SYS_IP_CONFIG
 572          * to bring up/down the virtual IP addresses, and PRIV_SYS_RESOURCE to
 573          * setrlimit().
 574          *
 575          * Note that sysevent is not supported in non-global zones.
 576          */
 577         if (getzoneid() == GLOBAL_ZONEID) {
 578                 err = __init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
 579                     PRIV_SYS_CONFIG, PRIV_NET_RAWACCESS, PRIV_NET_ICMPACCESS,
 580                     PRIV_SYS_IP_CONFIG, PRIV_SYS_RESOURCE, NULL);
 581         } else {
 582                 err = __init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0,
 583                     PRIV_NET_RAWACCESS, PRIV_NET_ICMPACCESS,
 584                     PRIV_SYS_IP_CONFIG, PRIV_SYS_RESOURCE, NULL);
 585         }
 586 
 587         if (err == -1) {
 588                 vrrp_log(VRRP_ERR, "main(): init_daemon_priv() failed");
 589                 return (EXIT_FAILURE);
 590         }
 591 
 592         /*
 593          * If vrrpd is started by other process, it will inherit the
 594          * signal block mask. We unblock all signals to make sure the
 595          * signal handling will work normally.
 596          */
 597         (void) sigfillset(&mask);
 598         (void) thr_sigsetmask(SIG_UNBLOCK, &mask, NULL);
 599         sa.sa_handler = vrrpd_cleanup;
 600         sa.sa_flags = 0;
 601         (void) sigemptyset(&sa.sa_mask);
 602         (void) sigaction(SIGINT, &sa, NULL);
 603         (void) sigaction(SIGQUIT, &sa, NULL);
 604         (void) sigaction(SIGTERM, &sa, NULL);
 605 
 606         vrrp_debug_level = 0;
 607         (void) strlcpy(vrrpd_conffile, VRRPCONF, sizeof (vrrpd_conffile));
 608         while ((c = getopt(argc, argv, "d:f:")) != EOF) {
 609                 switch (c) {
 610                 case 'd':
 611                         vrrp_debug_level = atoi(optarg);
 612                         break;
 613                 case 'f':
 614                         (void) strlcpy(vrrpd_conffile, optarg,
 615                             sizeof (vrrpd_conffile));
 616                         break;
 617                 default:
 618                         break;
 619                 }
 620         }
 621 
 622         closefrom(3);
 623         if (vrrp_debug_level == 0 && (daemon_init() != 0)) {
 624                 vrrp_log(VRRP_ERR, "main(): daemon_init() failed");
 625                 return (EXIT_FAILURE);
 626         }
 627 
 628         rl.rlim_cur = RLIM_INFINITY;
 629         rl.rlim_max = RLIM_INFINITY;
 630         if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
 631                 vrrp_log(VRRP_ERR, "main(): setrlimit() failed");
 632                 goto child_out;
 633         }
 634 
 635         if (vrrpd_init() != VRRP_SUCCESS) {
 636                 vrrp_log(VRRP_ERR, "main(): vrrpd_init() failed");
 637                 goto child_out;
 638         }
 639 
 640         /*
 641          * Get rid of unneeded privileges.
 642          */
 643         __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION,
 644             PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, PRIV_SYS_RESOURCE, NULL);
 645 
 646         /*
 647          * Read the configuration and initialize the existing VRRP
 648          * configuration
 649          */
 650         vrrpd_initconf();
 651 
 652         /*
 653          * Inform the parent process that it can successfully exit.
 654          */
 655         if ((err = vrrpd_inform_parent_exit(EXIT_SUCCESS)) != 0) {
 656                 vrrpd_cleanup();
 657                 vrrp_log(VRRP_WARNING, "vrrpd_inform_parent_exit() failed: %s",
 658                     strerror(err));
 659                 return (EXIT_FAILURE);
 660         }
 661 
 662         /*
 663          * Start the loop to handle the timer and the IO events.
 664          */
 665         switch (iu_handle_events(vrrpd_eh, vrrpd_timerq)) {
 666         case -1:
 667                 vrrp_log(VRRP_ERR, "main(): iu_handle_events() failed "
 668                     "abnormally");
 669                 break;
 670         default:
 671                 break;
 672         }
 673 
 674         vrrpd_cleanup();
 675         return (EXIT_SUCCESS);
 676 
 677 child_out:
 678         (void) vrrpd_inform_parent_exit(EXIT_FAILURE);
 679         return (EXIT_FAILURE);
 680 }
 681 
 682 static int
 683 daemon_init()
 684 {
 685         pid_t   pid;
 686         int     rv;
 687 
 688         vrrp_log(VRRP_DBG0, "daemon_init()");
 689 
 690         if (getenv("SMF_FMRI") == NULL) {
 691                 vrrp_log(VRRP_ERR, "daemon_init(): vrrpd is an smf(5) managed "
 692                     "service and should not be run from the command line.");
 693                 return (-1);
 694         }
 695 
 696         /*
 697          * Create the pipe used for the child process to inform the parent
 698          * process to exit after all initialization is done.
 699          */
 700         if (pipe(pfds) < 0) {
 701                 vrrp_log(VRRP_ERR, "daemon_init(): pipe() failed: %s",
 702                     strerror(errno));
 703                 return (-1);
 704         }
 705 
 706         if ((pid = fork()) < 0) {
 707                 vrrp_log(VRRP_ERR, "daemon_init(): fork() failed: %s",
 708                     strerror(errno));
 709                 (void) close(pfds[0]);
 710                 (void) close(pfds[1]);
 711                 return (-1);
 712         }
 713 
 714         if (pid != 0) { /* Parent */
 715                 (void) close(pfds[1]);
 716 
 717                 /*
 718                  * Read the child process's return value from the pfds.
 719                  * If the child process exits unexpectedly, read() returns -1.
 720                  */
 721                 if (read(pfds[0], &rv, sizeof (int)) != sizeof (int)) {
 722                         vrrp_log(VRRP_ERR, "daemon_init(): child process "
 723                             "exited unexpectedly %s", strerror(errno));
 724                         (void) kill(pid, SIGTERM);
 725                         rv = EXIT_FAILURE;
 726                 }
 727                 (void) close(pfds[0]);
 728                 exit(rv);
 729         }
 730 
 731         /*
 732          * in child process, became a daemon, and return to main() to continue.
 733          */
 734         (void) close(pfds[0]);
 735         (void) chdir("/");
 736         (void) setsid();
 737         (void) close(0);
 738         (void) close(1);
 739         (void) close(2);
 740         (void) open("/dev/null", O_RDWR, 0);
 741         (void) dup2(0, 1);
 742         (void) dup2(0, 2);
 743         openlog("vrrpd", LOG_PID, LOG_DAEMON);
 744         vrrp_logflag = 1;
 745         return (0);
 746 }
 747 
 748 static vrrp_err_t
 749 vrrpd_init()
 750 {
 751         vrrp_err_t      err = VRRP_ESYS;
 752 
 753         vrrp_log(VRRP_DBG0, "vrrpd_init()");
 754 
 755         TAILQ_INIT(&vrrp_vr_list);
 756         TAILQ_INIT(&vrrp_intf_list);
 757 
 758         if (vrrp_open(&vrrpd_vh) != VRRP_SUCCESS) {
 759                 vrrp_log(VRRP_ERR, "vrrpd_init(): vrrp_open() failed");
 760                 goto fail;
 761         }
 762 
 763         if ((vrrpd_timerq = iu_tq_create()) == NULL) {
 764                 vrrp_log(VRRP_ERR, "vrrpd_init(): iu_tq_create() failed");
 765                 goto fail;
 766         }
 767 
 768         if ((vrrpd_eh = iu_eh_create()) == NULL) {
 769                 vrrp_log(VRRP_ERR, "vrrpd_init(): iu_eh_create() failed");
 770                 goto fail;
 771         }
 772 
 773         /*
 774          * Create the AF_UNIX socket used to communicate with libvrrpadm.
 775          *
 776          * This socket is used to receive the administrative requests and
 777          * send back the results.
 778          */
 779         if (vrrpd_cmdsock_create() != VRRP_SUCCESS) {
 780                 vrrp_log(VRRP_ERR, "vrrpd_init(): vrrpd_cmdsock_create() "
 781                     "failed");
 782                 goto fail;
 783         }
 784 
 785         /*
 786          * Create the VRRP control socket used to bring up/down the virtual
 787          * IP addresses. It is also used to set the IFF_NOACCEPT flag of
 788          * the virtual IP addresses.
 789          */
 790         if (vrrpd_ctlsock_create() != VRRP_SUCCESS) {
 791                 vrrp_log(VRRP_ERR, "vrrpd_init(): vrrpd_ctlsock_create() "
 792                     "failed");
 793                 goto fail;
 794         }
 795 
 796         /*
 797          * Create the PF_ROUTER socket used to listen to the routing socket
 798          * messages and build the interface/IP address list.
 799          */
 800         if (vrrpd_rtsock_create() != VRRP_SUCCESS) {
 801                 vrrp_log(VRRP_ERR, "vrrpd_init(): vrrpd_rtsock_create() "
 802                     "failed");
 803                 goto fail;
 804         }
 805 
 806         /* Open the libipadm handle */
 807         if (ipadm_open(&vrrp_ipadm_handle, 0) != IPADM_SUCCESS) {
 808                 vrrp_log(VRRP_ERR, "vrrpd_init(): ipadm_open() failed");
 809                 goto fail;
 810         }
 811 
 812         /*
 813          * Build the list of interfaces and IP addresses. Also, start the time
 814          * to scan the interfaces/IP addresses periodically.
 815          */
 816         vrrpd_scan(AF_INET);
 817         vrrpd_scan(AF_INET6);
 818         if ((vrrp_scan_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
 819             vrrpd_scan_interval, vrrpd_scan_timer, NULL)) == -1) {
 820                 vrrp_log(VRRP_ERR, "vrrpd_init(): start scan_timer failed");
 821                 goto fail;
 822         }
 823 
 824         /*
 825          * Initialize the VRRP multicast address.
 826          */
 827         bzero(&vrrp_muladdr4, sizeof (vrrp_addr_t));
 828         vrrp_muladdr4.in4.sin_family = AF_INET;
 829         (void) inet_pton(AF_INET, "224.0.0.18", &vrrp_muladdr4.in4.sin_addr);
 830 
 831         bzero(&vrrp_muladdr6, sizeof (vrrp_addr_t));
 832         vrrp_muladdr6.in6.sin6_family = AF_INET6;
 833         (void) inet_pton(AF_INET6, "ff02::12", &vrrp_muladdr6.in6.sin6_addr);
 834 
 835         return (VRRP_SUCCESS);
 836 
 837 fail:
 838         vrrpd_fini();
 839         return (err);
 840 }
 841 
 842 static void
 843 vrrpd_fini()
 844 {
 845         vrrp_log(VRRP_DBG0, "vrrpd_fini()");
 846 
 847         (void) iu_cancel_timer(vrrpd_timerq, vrrp_scan_timer_id, NULL);
 848         vrrp_scan_timer_id = -1;
 849 
 850         vrrpd_rtsock_destroy();
 851         vrrpd_ctlsock_destroy();
 852         vrrpd_cmdsock_destroy();
 853 
 854         if (vrrpd_eh != NULL) {
 855                 iu_eh_destroy(vrrpd_eh);
 856                 vrrpd_eh = NULL;
 857         }
 858 
 859         if (vrrpd_timerq != NULL) {
 860                 iu_tq_destroy(vrrpd_timerq);
 861                 vrrpd_timerq = NULL;
 862         }
 863 
 864         vrrp_close(vrrpd_vh);
 865         vrrpd_vh = NULL;
 866         assert(TAILQ_EMPTY(&vrrp_vr_list));
 867         assert(TAILQ_EMPTY(&vrrp_intf_list));
 868 
 869         ipadm_close(vrrp_ipadm_handle);
 870 }
 871 
 872 static void
 873 vrrpd_cleanup(void)
 874 {
 875         vrrp_vr_t       *vr;
 876         vrrp_intf_t     *intf;
 877 
 878         vrrp_log(VRRP_DBG0, "vrrpd_cleanup()");
 879 
 880         while (!TAILQ_EMPTY(&vrrp_vr_list)) {
 881                 vr = TAILQ_FIRST(&vrrp_vr_list);
 882                 vrrpd_delete_vr(vr);
 883         }
 884 
 885         while (!TAILQ_EMPTY(&vrrp_intf_list)) {
 886                 intf = TAILQ_FIRST(&vrrp_intf_list);
 887                 vrrpd_delete_if(intf, _B_FALSE);
 888         }
 889 
 890         vrrpd_fini();
 891         closelog();
 892         exit(1);
 893 }
 894 
 895 /*
 896  * Read the configuration file and initialize all the existing VRRP routers.
 897  */
 898 static void
 899 vrrpd_initconf()
 900 {
 901         FILE *fp;
 902         char line[LINE_MAX];
 903         int linenum = 0;
 904         vrrp_vr_conf_t conf;
 905         vrrp_err_t err;
 906 
 907         vrrp_log(VRRP_DBG0, "vrrpd_initconf()");
 908 
 909         if ((fp = fopen(vrrpd_conffile, "rF")) == NULL) {
 910                 vrrp_log(VRRP_ERR, "failed to open the configuration file %s",
 911                     vrrpd_conffile);
 912                 return;
 913         }
 914 
 915         while (fgets(line, sizeof (line), fp) != NULL) {
 916                 linenum++;
 917                 conf.vvc_vrid = VRRP_VRID_NONE;
 918                 if ((err = vrrpd_read_vrconf(line, &conf)) != VRRP_SUCCESS) {
 919                         vrrp_log(VRRP_ERR, "failed to parse %d line %s",
 920                             linenum, line);
 921                         continue;
 922                 }
 923 
 924                 /*
 925                  * Blank or comment line
 926                  */
 927                 if (conf.vvc_vrid == VRRP_VRID_NONE)
 928                         continue;
 929 
 930                 /*
 931                  * No need to update the configuration since the VRRP router
 932                  * created/enabled based on the existing configuration.
 933                  */
 934                 if ((err = vrrpd_create(&conf, _B_FALSE)) != VRRP_SUCCESS) {
 935                         vrrp_log(VRRP_ERR, "VRRP router %s creation failed: "
 936                             "%s", conf.vvc_name, vrrp_err2str(err));
 937                         continue;
 938                 }
 939 
 940                 if (conf.vvc_enabled &&
 941                     ((err = vrrpd_enable(conf.vvc_name, _B_FALSE)) !=
 942                     VRRP_SUCCESS)) {
 943                         vrrp_log(VRRP_ERR, "VRRP router %s enable failed: %s",
 944                             conf.vvc_name, vrrp_err2str(err));
 945                 }
 946         }
 947 
 948         (void) fclose(fp);
 949 }
 950 
 951 /*
 952  * Create the AF_UNIX socket used to communicate with libvrrpadm.
 953  *
 954  * This socket is used to receive the administrative request and
 955  * send back the results.
 956  */
 957 static vrrp_err_t
 958 vrrpd_cmdsock_create()
 959 {
 960         iu_event_id_t           eid;
 961         struct sockaddr_un      laddr;
 962         int                     sock, flags;
 963 
 964         vrrp_log(VRRP_DBG0, "vrrpd_cmdsock_create()");
 965 
 966         if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
 967                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): socket(AF_UNIX) "
 968                     "failed: %s", strerror(errno));
 969                 return (VRRP_ESYS);
 970         }
 971 
 972         /*
 973          * Set it to be non-blocking.
 974          */
 975         flags = fcntl(sock, F_GETFL, 0);
 976         (void) fcntl(sock, F_SETFL, (flags | O_NONBLOCK));
 977 
 978         /*
 979          * Unlink first in case a previous daemon instance exited ungracefully.
 980          */
 981         (void) unlink(VRRPD_SOCKET);
 982 
 983         bzero(&laddr, sizeof (laddr));
 984         laddr.sun_family = AF_UNIX;
 985         (void) strlcpy(laddr.sun_path, VRRPD_SOCKET, sizeof (laddr.sun_path));
 986         if (bind(sock, (struct sockaddr *)&laddr, sizeof (laddr)) < 0) {
 987                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): bind() failed: %s",
 988                     strerror(errno));
 989                 (void) close(sock);
 990                 return (VRRP_ESYS);
 991         }
 992 
 993         if (listen(sock, 30) < 0) {
 994                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): listen() "
 995                     "failed: %s", strerror(errno));
 996                 (void) close(sock);
 997                 return (VRRP_ESYS);
 998         }
 999 
1000         if ((eid = iu_register_event(vrrpd_eh, sock, POLLIN,
1001             vrrpd_cmdsock_handler, NULL)) == -1) {
1002                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_create(): iu_register_event()"
1003                     " failed");
1004                 (void) close(sock);
1005                 return (VRRP_ESYS);
1006         }
1007 
1008         vrrpd_cmdsock_fd = sock;
1009         vrrpd_cmdsock_eid = eid;
1010         return (VRRP_SUCCESS);
1011 }
1012 
1013 static void
1014 vrrpd_cmdsock_destroy()
1015 {
1016         vrrp_log(VRRP_DBG0, "vrrpd_cmdsock_destroy()");
1017 
1018         (void) iu_unregister_event(vrrpd_eh, vrrpd_cmdsock_eid, NULL);
1019         (void) close(vrrpd_cmdsock_fd);
1020         vrrpd_cmdsock_fd = -1;
1021         vrrpd_cmdsock_eid = -1;
1022 }
1023 
1024 /*
1025  * Create the PF_ROUTER sockets used to listen to the routing socket
1026  * messages and build the interface/IP address list. Create one for
1027  * each address family (IPv4 and IPv6).
1028  */
1029 static vrrp_err_t
1030 vrrpd_rtsock_create()
1031 {
1032         int             i, flags, sock;
1033         iu_event_id_t   eid;
1034 
1035         vrrp_log(VRRP_DBG0, "vrrpd_rtsock_create()");
1036 
1037         for (i = 0; i < 2; i++) {
1038                 sock = socket(PF_ROUTE, SOCK_RAW, vrrpd_rtsocks[i].vrt_af);
1039                 if (sock == -1) {
1040                         vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): socket() "
1041                             "failed: %s", strerror(errno));
1042                         break;
1043                 }
1044 
1045                 /*
1046                  * Set it to be non-blocking.
1047                  */
1048                 if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
1049                         vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): "
1050                             "fcntl(F_GETFL) failed: %s", strerror(errno));
1051                         break;
1052                 }
1053 
1054                 if ((fcntl(sock, F_SETFL, flags | O_NONBLOCK)) < 0) {
1055                         vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): "
1056                             "fcntl(F_SETFL) failed: %s", strerror(errno));
1057                         break;
1058                 }
1059 
1060                 if ((eid = iu_register_event(vrrpd_eh, sock, POLLIN,
1061                     vrrpd_rtsock_handler, &(vrrpd_rtsocks[i].vrt_af))) == -1) {
1062                         vrrp_log(VRRP_ERR, "vrrpd_rtsock_create(): register "
1063                             "rtsock %d(%s) failed", sock,
1064                             af_str(vrrpd_rtsocks[i].vrt_af));
1065                         break;
1066                 }
1067 
1068                 vrrpd_rtsocks[i].vrt_fd = sock;
1069                 vrrpd_rtsocks[i].vrt_eid = eid;
1070         }
1071 
1072         if (i != 2) {
1073                 (void) close(sock);
1074                 vrrpd_rtsock_destroy();
1075                 return (VRRP_ESYS);
1076         }
1077 
1078         return (VRRP_SUCCESS);
1079 }
1080 
1081 static void
1082 vrrpd_rtsock_destroy()
1083 {
1084         int             i;
1085 
1086         vrrp_log(VRRP_DBG0, "vrrpd_rtsock_destroy()");
1087         for (i = 0; i < 2; i++) {
1088                 (void) iu_unregister_event(vrrpd_eh, vrrpd_rtsocks[i].vrt_eid,
1089                     NULL);
1090                 (void) close(vrrpd_rtsocks[i].vrt_fd);
1091                 vrrpd_rtsocks[i].vrt_eid = -1;
1092                 vrrpd_rtsocks[i].vrt_fd = -1;
1093         }
1094 }
1095 
1096 /*
1097  * Create the VRRP control socket used to bring up/down the virtual
1098  * IP addresses. It is also used to set the IFF_NOACCEPT flag of
1099  * the virtual IP addresses.
1100  */
1101 static vrrp_err_t
1102 vrrpd_ctlsock_create()
1103 {
1104         int     s, s6;
1105         int     on = _B_TRUE;
1106 
1107         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1108                 vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): socket(INET) "
1109                     "failed: %s", strerror(errno));
1110                 return (VRRP_ESYS);
1111         }
1112         if (setsockopt(s, SOL_SOCKET, SO_VRRP, &on, sizeof (on)) < 0) {
1113                 vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): "
1114                     "setsockopt(INET, SO_VRRP) failed: %s", strerror(errno));
1115                 (void) close(s);
1116                 return (VRRP_ESYS);
1117         }
1118 
1119         if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1120                 vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): socket(INET6) "
1121                     "failed: %s", strerror(errno));
1122                 (void) close(s);
1123                 return (VRRP_ESYS);
1124         }
1125         if (setsockopt(s6, SOL_SOCKET, SO_VRRP, &on, sizeof (on)) < 0) {
1126                 vrrp_log(VRRP_ERR, "vrrpd_ctlsock_create(): "
1127                     "setsockopt(INET6, SO_VRRP) failed: %s", strerror(errno));
1128                 (void) close(s);
1129                 (void) close(s6);
1130                 return (VRRP_ESYS);
1131         }
1132 
1133         vrrpd_ctlsock_fd = s;
1134         vrrpd_ctlsock6_fd = s6;
1135         return (VRRP_SUCCESS);
1136 }
1137 
1138 static void
1139 vrrpd_ctlsock_destroy()
1140 {
1141         (void) close(vrrpd_ctlsock_fd);
1142         vrrpd_ctlsock_fd = -1;
1143         (void) close(vrrpd_ctlsock6_fd);
1144         vrrpd_ctlsock6_fd = -1;
1145 }
1146 
1147 /*ARGSUSED*/
1148 static void
1149 vrrpd_cmd_create(void *arg1, void *arg2, size_t *arg2_sz)
1150 {
1151         vrrp_cmd_create_t       *cmd = (vrrp_cmd_create_t *)arg1;
1152         vrrp_ret_create_t       *ret = (vrrp_ret_create_t *)arg2;
1153         vrrp_err_t              err;
1154 
1155         err = vrrpd_create(&cmd->vcc_conf, _B_TRUE);
1156         if (err == VRRP_SUCCESS && cmd->vcc_conf.vvc_enabled) {
1157                 /*
1158                  * No need to update the configuration since it is already
1159                  * done in the above vrrpd_create() call
1160                  */
1161                 err = vrrpd_enable(cmd->vcc_conf.vvc_name, _B_FALSE);
1162                 if (err != VRRP_SUCCESS)
1163                         (void) vrrpd_delete(cmd->vcc_conf.vvc_name);
1164         }
1165         ret->vrc_err = err;
1166 }
1167 
1168 /*ARGSUSED*/
1169 static void
1170 vrrpd_cmd_delete(void *arg1, void *arg2, size_t *arg2_sz)
1171 {
1172         vrrp_cmd_delete_t       *cmd = (vrrp_cmd_delete_t *)arg1;
1173         vrrp_ret_delete_t       *ret = (vrrp_ret_delete_t *)arg2;
1174 
1175         ret->vrd_err = vrrpd_delete(cmd->vcd_name);
1176 }
1177 
1178 /*ARGSUSED*/
1179 static void
1180 vrrpd_cmd_enable(void *arg1, void *arg2, size_t *arg2_sz)
1181 {
1182         vrrp_cmd_enable_t       *cmd = (vrrp_cmd_enable_t *)arg1;
1183         vrrp_ret_enable_t       *ret = (vrrp_ret_enable_t *)arg2;
1184 
1185         ret->vrs_err = vrrpd_enable(cmd->vcs_name, _B_TRUE);
1186 }
1187 
1188 /*ARGSUSED*/
1189 static void
1190 vrrpd_cmd_disable(void *arg1, void *arg2, size_t *arg2_sz)
1191 {
1192         vrrp_cmd_disable_t      *cmd = (vrrp_cmd_disable_t *)arg1;
1193         vrrp_ret_disable_t      *ret = (vrrp_ret_disable_t *)arg2;
1194 
1195         ret->vrx_err = vrrpd_disable(cmd->vcx_name);
1196 }
1197 
1198 /*ARGSUSED*/
1199 static void
1200 vrrpd_cmd_modify(void *arg1, void *arg2, size_t *arg2_sz)
1201 {
1202         vrrp_cmd_modify_t       *cmd = (vrrp_cmd_modify_t *)arg1;
1203         vrrp_ret_modify_t       *ret = (vrrp_ret_modify_t *)arg2;
1204 
1205         ret->vrm_err = vrrpd_modify(&cmd->vcm_conf, cmd->vcm_mask);
1206 }
1207 
1208 static void
1209 vrrpd_cmd_query(void *arg1, void *arg2, size_t *arg2_sz)
1210 {
1211         vrrp_cmd_query_t        *cmd = (vrrp_cmd_query_t *)arg1;
1212 
1213         vrrpd_query(cmd->vcq_name, arg2, arg2_sz);
1214 }
1215 
1216 static void
1217 vrrpd_cmd_list(void *arg1, void *arg2, size_t *arg2_sz)
1218 {
1219         vrrp_cmd_list_t *cmd = (vrrp_cmd_list_t *)arg1;
1220 
1221         vrrpd_list(cmd->vcl_vrid, cmd->vcl_ifname, cmd->vcl_af, arg2, arg2_sz);
1222 }
1223 
1224 /*
1225  * Write-type requeset must have the solaris.network.vrrp authorization.
1226  */
1227 static boolean_t
1228 vrrp_auth_check(int connfd, vrrp_cmd_info_t *cinfo)
1229 {
1230         ucred_t         *cred = NULL;
1231         uid_t           uid;
1232         struct passwd   *pw;
1233         boolean_t       success = _B_FALSE;
1234 
1235         vrrp_log(VRRP_DBG0, "vrrp_auth_check()");
1236 
1237         if (!cinfo->vi_setop)
1238                 return (_B_TRUE);
1239 
1240         /*
1241          * Validate the credential
1242          */
1243         if (getpeerucred(connfd, &cred) == (uid_t)-1) {
1244                 vrrp_log(VRRP_ERR, "vrrp_auth_check(): getpeerucred() "
1245                     "failed: %s", strerror(errno));
1246                 return (_B_FALSE);
1247         }
1248 
1249         if ((uid = ucred_getruid((const ucred_t *)cred)) == (uid_t)-1) {
1250                 vrrp_log(VRRP_ERR, "vrrp_auth_check(): ucred_getruid() "
1251                     "failed: %s", strerror(errno));
1252                 goto done;
1253         }
1254 
1255         if ((pw = getpwuid(uid)) == NULL) {
1256                 vrrp_log(VRRP_ERR, "vrrp_auth_check(): getpwuid() failed");
1257                 goto done;
1258         }
1259 
1260         success = (chkauthattr("solaris.network.vrrp", pw->pw_name) == 1);
1261 
1262 done:
1263         ucred_free(cred);
1264         return (success);
1265 }
1266 
1267 /*
1268  * Process the administrative request from libvrrpadm
1269  */
1270 /* ARGSUSED */
1271 static void
1272 vrrpd_cmdsock_handler(iu_eh_t *eh, int s, short events, iu_event_id_t id,
1273     void *arg)
1274 {
1275         vrrp_cmd_info_t         *cinfo = NULL;
1276         vrrp_err_t              err = VRRP_SUCCESS;
1277         uchar_t                 buf[BUFFSIZE], ackbuf[BUFFSIZE];
1278         size_t                  cursize, acksize, len;
1279         uint32_t                cmd;
1280         int                     connfd, i;
1281         struct sockaddr_in      from;
1282         socklen_t               fromlen;
1283 
1284         vrrp_log(VRRP_DBG0, "vrrpd_cmdsock_handler()");
1285 
1286         fromlen = (socklen_t)sizeof (from);
1287         if ((connfd = accept(s, (struct sockaddr *)&from, &fromlen)) < 0) {
1288                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler() accept(): %s",
1289                     strerror(errno));
1290                 return;
1291         }
1292 
1293         /*
1294          * First get the type of the request
1295          */
1296         cursize = 0;
1297         while (cursize < sizeof (uint32_t)) {
1298                 len = read(connfd, buf + cursize,
1299                     sizeof (uint32_t) - cursize);
1300                 if (len == (size_t)-1 && (errno == EAGAIN || errno == EINTR)) {
1301                         continue;
1302                 } else if (len > 0) {
1303                         cursize += len;
1304                         continue;
1305                 }
1306                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): invalid message "
1307                     "length");
1308                 (void) close(connfd);
1309                 return;
1310         }
1311 
1312         /* LINTED E_BAD_PTR_CAST_ALIGN */
1313         cmd = ((vrrp_cmd_t *)buf)->vc_cmd;
1314         for (i = 0; i < VRRP_DOOR_INFO_TABLE_SIZE; i++) {
1315                 if (vrrp_cmd_info_tbl[i].vi_cmd == cmd) {
1316                         cinfo = vrrp_cmd_info_tbl + i;
1317                         break;
1318                 }
1319         }
1320 
1321         if (cinfo == NULL) {
1322                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): invalid request "
1323                     "type %d", cmd);
1324                 err = VRRP_EINVAL;
1325                 goto done;
1326         }
1327 
1328         /*
1329          * Get the rest of the request.
1330          */
1331         assert(cursize == sizeof (uint32_t));
1332         while (cursize < cinfo->vi_reqsize) {
1333                 len = read(connfd, buf + cursize,
1334                     cinfo->vi_reqsize - cursize);
1335                 if (len == (size_t)-1 && (errno == EAGAIN || errno == EINTR)) {
1336                         continue;
1337                 } else if (len > 0) {
1338                         cursize += len;
1339                         continue;
1340                 }
1341                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): invalid message "
1342                     "length");
1343                 err = VRRP_EINVAL;
1344                 goto done;
1345         }
1346 
1347         /*
1348          * Validate the authorization
1349          */
1350         if (!vrrp_auth_check(connfd, cinfo)) {
1351                 vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler(): "
1352                     "not sufficient authorization");
1353                 err = VRRP_EPERM;
1354         }
1355 
1356 done:
1357         /*
1358          * Ack the request
1359          */
1360         if (err != 0) {
1361                 /* LINTED E_BAD_PTR_CAST_ALIGN */
1362                 ((vrrp_ret_t *)ackbuf)->vr_err = err;
1363                 acksize = sizeof (vrrp_ret_t);
1364         } else {
1365                 /*
1366                  * If the size of ack is varied, the cmdfunc callback
1367                  * will set the right size.
1368                  */
1369                 if ((acksize = cinfo->vi_acksize) == 0)
1370                         acksize = sizeof (ackbuf);
1371 
1372                 /* LINTED E_BAD_PTR_CAST_ALIGN */
1373                 cinfo->vi_cmdfunc((vrrp_cmd_t *)buf, ackbuf, &acksize);
1374         }
1375 
1376         /*
1377          * Send the ack back.
1378          */
1379         cursize = 0;
1380         while (cursize < acksize) {
1381                 len = sendto(connfd, ackbuf + cursize, acksize - cursize,
1382                     0, (struct sockaddr *)&from, fromlen);
1383                 if (len == (size_t)-1 && errno == EAGAIN) {
1384                         continue;
1385                 } else if (len > 0) {
1386                         cursize += len;
1387                         continue;
1388                 } else {
1389                         vrrp_log(VRRP_ERR, "vrrpd_cmdsock_handler() failed to "
1390                             "ack: %s", strerror(errno));
1391                         break;
1392                 }
1393         }
1394 
1395         (void) shutdown(connfd, SHUT_RDWR);
1396         (void) close(connfd);
1397 }
1398 
1399 /*
1400  * Process the routing socket messages and update the interfaces/IP addresses
1401  * list
1402  */
1403 /* ARGSUSED */
1404 static void
1405 vrrpd_rtsock_handler(iu_eh_t *eh, int s, short events,
1406     iu_event_id_t id, void *arg)
1407 {
1408         char                    buf[BUFFSIZE];
1409         struct ifa_msghdr       *ifam;
1410         int                     nbytes;
1411         int                     af = *(int *)arg;
1412         boolean_t               scanif = _B_FALSE;
1413 
1414         for (;;) {
1415                 nbytes = read(s, buf, sizeof (buf));
1416                 if (nbytes <= 0) {
1417                         /* No more messages */
1418                         break;
1419                 }
1420 
1421                 /* LINTED E_BAD_PTR_CAST_ALIGN */
1422                 ifam = (struct ifa_msghdr *)buf;
1423                 if (ifam->ifam_version != RTM_VERSION) {
1424                         vrrp_log(VRRP_ERR, "vrrpd_rtsock_handler(): version %d "
1425                             "not understood", ifam->ifam_version);
1426                         break;
1427                 }
1428 
1429                 vrrp_log(VRRP_DBG0, "vrrpd_rtsock_handler(): recv %s event",
1430                     rtm_event2str(ifam->ifam_type));
1431 
1432                 switch (ifam->ifam_type) {
1433                 case RTM_FREEADDR:
1434                 case RTM_CHGADDR:
1435                 case RTM_NEWADDR:
1436                 case RTM_DELADDR:
1437                         /*
1438                          * An IP address has been created/updated/deleted or
1439                          * brought up/down, re-initilialize the interface/IP
1440                          * address list.
1441                          */
1442                         scanif = _B_TRUE;
1443                         break;
1444                 default:
1445                         /* Not interesting */
1446                         break;
1447                 }
1448         }
1449 
1450         if (scanif)
1451                 vrrpd_scan(af);
1452 }
1453 
1454 /*
1455  * Periodically scan the interface/IP addresses on the system.
1456  */
1457 /* ARGSUSED */
1458 static void
1459 vrrpd_scan_timer(iu_tq_t *tq, void *arg)
1460 {
1461         vrrp_log(VRRP_DBG0, "vrrpd_scan_timer()");
1462         vrrpd_scan(AF_INET);
1463         vrrpd_scan(AF_INET6);
1464 }
1465 
1466 /*
1467  * Get the list of the interface/IP addresses of the specified address
1468  * family.
1469  */
1470 static void
1471 vrrpd_scan(int af)
1472 {
1473         vrrp_log(VRRP_DBG0, "vrrpd_scan(%s)", af_str(af));
1474 
1475 again:
1476         vrrpd_init_ipcache(af);
1477 
1478         /* If interface index changes, walk again. */
1479         if (vrrpd_walk_addr_info(af) != IPADM_SUCCESS)
1480                 goto again;
1481 
1482         vrrpd_update_ipcache(af);
1483 }
1484 
1485 /*
1486  * First mark all IP addresses of the specific address family to be removed.
1487  * This flag will then be cleared when we walk up all the IP addresses.
1488  */
1489 static void
1490 vrrpd_init_ipcache(int af)
1491 {
1492         vrrp_intf_t     *intf, *next_intf;
1493         vrrp_ip_t       *ip, *nextip;
1494         char            abuf[INET6_ADDRSTRLEN];
1495 
1496         vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(%s)", af_str(af));
1497 
1498         next_intf = TAILQ_FIRST(&vrrp_intf_list);
1499         while ((intf = next_intf) != NULL) {
1500                 next_intf = TAILQ_NEXT(intf, vvi_next);
1501                 if (intf->vvi_af != af)
1502                         continue;
1503 
1504                 /*
1505                  * If the interface is still marked as new, it means that this
1506                  * vrrpd_init_ipcache() call is a result of ifindex change,
1507                  * which causes the re-walk of all the interfaces (see
1508                  * vrrpd_add_ipaddr()), and some interfaces are still marked
1509                  * as new during the last walk. In this case, delete this
1510                  * interface with the "update_vr" argument to be _B_FALSE,
1511                  * since no VRRP router has been assoicated with this
1512                  * interface yet (the association is done in
1513                  * vrrpd_update_ipcache()).
1514                  *
1515                  * This interface will be re-added later if it still exists.
1516                  */
1517                 if (intf->vvi_state == NODE_STATE_NEW) {
1518                         vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(): remove %s "
1519                             "(%d), may be added later", intf->vvi_ifname,
1520                             intf->vvi_ifindex);
1521                         vrrpd_delete_if(intf, _B_FALSE);
1522                         continue;
1523                 }
1524 
1525                 for (ip = TAILQ_FIRST(&intf->vvi_iplist); ip != NULL;
1526                     ip = nextip) {
1527                         nextip = TAILQ_NEXT(ip, vip_next);
1528                         /* LINTED E_CONSTANT_CONDITION */
1529                         VRRPADDR2STR(af, &ip->vip_addr, abuf,
1530                             INET6_ADDRSTRLEN, _B_FALSE);
1531 
1532                         if (ip->vip_state != NODE_STATE_NEW) {
1533                                 vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(%s/%d, "
1534                                     "%s(%s/0x%x))", intf->vvi_ifname,
1535                                     intf->vvi_ifindex, ip->vip_lifname,
1536                                     abuf, ip->vip_flags);
1537                                 ip->vip_state = NODE_STATE_STALE;
1538                                 continue;
1539                         }
1540 
1541                         /*
1542                          * If the IP is still marked as new, it means that
1543                          * this vrrpd_init_ipcache() call is a result of
1544                          * ifindex change, which causes the re-walk of all
1545                          * the IP addresses (see vrrpd_add_ipaddr()).
1546                          * Delete this IP.
1547                          *
1548                          * This IP will be readded later if it still exists.
1549                          */
1550                         vrrp_log(VRRP_DBG0, "vrrpd_init_ipcache(): remove "
1551                             "%s/%d , %s(%s)", intf->vvi_ifname,
1552                             intf->vvi_ifindex, ip->vip_lifname, abuf);
1553                         vrrpd_delete_ip(intf, ip);
1554                 }
1555         }
1556 }
1557 
1558 /*
1559  * Walk all the IP addresses of the given family and update its
1560  * addresses list. Return IPADM_FAILURE if it is required to walk
1561  * all the interfaces again (one of the interface index changes in between).
1562  */
1563 static ipadm_status_t
1564 vrrpd_walk_addr_info(int af)
1565 {
1566         ipadm_addr_info_t       *ainfo, *ainfop;
1567         ipadm_status_t          ipstatus;
1568         char                    *lifname;
1569         struct sockaddr_storage stor;
1570         vrrp_addr_t             *addr;
1571         int                     ifindex;
1572         uint64_t                flags;
1573 
1574         vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s)", af_str(af));
1575 
1576         ipstatus = ipadm_addr_info(vrrp_ipadm_handle, NULL, &ainfo, 0, 0);
1577         if (ipstatus != IPADM_SUCCESS) {
1578                 vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): "
1579                     "ipadm_addr_info() failed: %s",
1580                     af_str(af), ipadm_status2str(ipstatus));
1581                 return (IPADM_SUCCESS);
1582         }
1583 
1584         for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
1585                 if (ainfop->ia_ifa.ifa_addr->sa_family != af)
1586                         continue;
1587 
1588                 lifname = ainfop->ia_ifa.ifa_name;
1589                 flags = ainfop->ia_ifa.ifa_flags;
1590                 (void) memcpy(&stor, ainfop->ia_ifa.ifa_addr, sizeof (stor));
1591                 addr = (vrrp_addr_t *)&stor;
1592 
1593                 vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): %s",
1594                     af_str(af), lifname);
1595 
1596                 /* Skip virtual/IPMP/P2P interfaces */
1597                 if (flags & (IFF_VIRTUAL|IFF_IPMP|IFF_POINTOPOINT)) {
1598                         vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): "
1599                             "skipped %s", af_str(af), lifname);
1600                         continue;
1601                 }
1602 
1603                 /* Filter out the all-zero IP address */
1604                 if (VRRPADDR_UNSPECIFIED(af, addr))
1605                         continue;
1606 
1607                 if ((ifindex = if_nametoindex(lifname)) == 0) {
1608                         if (errno != ENXIO && errno != ENOENT) {
1609                                 vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): "
1610                                     "if_nametoindex() failed for %s: %s",
1611                                     af_str(af), lifname, strerror(errno));
1612                         }
1613                         break;
1614                 }
1615 
1616                 /*
1617                  * The interface is unplumbed/replumbed during the walk.  Try
1618                  * to walk the IP addresses one more time.
1619                  */
1620                 if (vrrpd_add_ipaddr(lifname, af, addr, ifindex, flags)
1621                     == VRRP_EAGAIN) {
1622                         ipstatus = IPADM_FAILURE;
1623                         break;
1624                 }
1625         }
1626 
1627         ipadm_free_addr_info(ainfo);
1628         return (ipstatus);
1629 }
1630 
1631 /*
1632  * Given the information of each IP address, update the interface and
1633  * IP addresses list
1634  */
1635 static vrrp_err_t
1636 vrrpd_add_ipaddr(char *lifname, int af, vrrp_addr_t *addr, int ifindex,
1637     uint64_t flags)
1638 {
1639         char            ifname[LIFNAMSIZ], *c;
1640         vrrp_intf_t     *intf;
1641         vrrp_ip_t       *ip;
1642         char            abuf[INET6_ADDRSTRLEN];
1643         vrrp_err_t      err;
1644 
1645         /* LINTED E_CONSTANT_CONDITION */
1646         VRRPADDR2STR(af, addr, abuf, INET6_ADDRSTRLEN, _B_FALSE);
1647         vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s, %s, %d, 0x%x)", lifname,
1648             abuf, ifindex, flags);
1649 
1650         /*
1651          * Get the physical interface name from the logical interface name.
1652          */
1653         (void) strlcpy(ifname, lifname, sizeof (ifname));
1654         if ((c = strchr(ifname, ':')) != NULL)
1655                 *c = '\0';
1656 
1657         if ((intf = vrrpd_lookup_if(ifname, af)) == NULL) {
1658                 vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(): %s is new", ifname);
1659                 err = vrrpd_create_if(ifname, af, ifindex, &intf);
1660                 if (err != VRRP_SUCCESS)
1661                         return (err);
1662         } else if (intf->vvi_ifindex != ifindex) {
1663                 /*
1664                  * If index changes, it means that this interface is
1665                  * unplumbed/replumbed since we last checked. If this
1666                  * interface is not used by any VRRP router, just
1667                  * update its ifindex, and the IP addresses list will
1668                  * be updated later. Otherwise, return EAGAIN to rewalk
1669                  * all the IP addresses from the beginning.
1670                  */
1671                 vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s) ifindex changed ",
1672                     "from %d to %d", ifname, intf->vvi_ifindex, ifindex);
1673                 if (!IS_PRIMARY_INTF(intf) && !IS_VIRTUAL_INTF(intf)) {
1674                         intf->vvi_ifindex = ifindex;
1675                 } else {
1676                         /*
1677                          * delete this interface from the list if this
1678                          * interface has already been assoicated with
1679                          * any VRRP routers.
1680                          */
1681                         vrrpd_delete_if(intf, _B_TRUE);
1682                         return (VRRP_EAGAIN);
1683                 }
1684         }
1685 
1686         /*
1687          * Does this IP address already exist?
1688          */
1689         TAILQ_FOREACH(ip, &intf->vvi_iplist, vip_next) {
1690                 if (strcmp(ip->vip_lifname, lifname) == 0)
1691                         break;
1692         }
1693 
1694         if (ip != NULL) {
1695                 vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s, %s) IP exists",
1696                     lifname, abuf);
1697                 ip->vip_state = NODE_STATE_NONE;
1698                 ip->vip_flags = flags;
1699                 if (ipaddr_cmp(af, addr, &ip->vip_addr) != 0) {
1700                         /*
1701                          * Address has been changed, mark it as new
1702                          * If this address is already selected as the
1703                          * primary IP address, the new IP will be checked
1704                          * to see whether it is still qualified as the
1705                          * primary IP address. If not, the primary IP
1706                          * address will be reselected.
1707                          */
1708                         (void) memcpy(&ip->vip_addr, addr,
1709                             sizeof (vrrp_addr_t));
1710 
1711                         ip->vip_state = NODE_STATE_NEW;
1712                 }
1713         } else {
1714                 vrrp_log(VRRP_DBG0, "vrrpd_add_ipaddr(%s, %s) IP is new",
1715                     lifname, abuf);
1716 
1717                 err = vrrpd_create_ip(intf, lifname, addr, flags);
1718                 if (err != VRRP_SUCCESS)
1719                         return (err);
1720         }
1721         return (VRRP_SUCCESS);
1722 }
1723 
1724 /*
1725  * Update the interface and IP addresses list. Remove the ones that have been
1726  * staled since last time we walk the IP addresses and updated the ones that
1727  * have been changed.
1728  */
1729 static void
1730 vrrpd_update_ipcache(int af)
1731 {
1732         vrrp_intf_t     *intf, *nextif;
1733         vrrp_ip_t       *ip, *nextip;
1734         char            abuf[INET6_ADDRSTRLEN];
1735         boolean_t       primary_selected;
1736         boolean_t       primary_now_selected;
1737         boolean_t       need_reenable = _B_FALSE;
1738 
1739         vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(%s)", af_str(af));
1740 
1741         nextif = TAILQ_FIRST(&vrrp_intf_list);
1742         while ((intf = nextif) != NULL) {
1743                 nextif = TAILQ_NEXT(intf, vvi_next);
1744                 if (intf->vvi_af != af)
1745                         continue;
1746 
1747                 /*
1748                  * Does the interface already select its primary IP address?
1749                  */
1750                 primary_selected = (intf->vvi_pip != NULL);
1751                 assert(!primary_selected || IS_PRIMARY_INTF(intf));
1752 
1753                 /*
1754                  * Removed the IP addresses that have been unconfigured.
1755                  */
1756                 for (ip = TAILQ_FIRST(&intf->vvi_iplist); ip != NULL;
1757                     ip = nextip) {
1758                         nextip = TAILQ_NEXT(ip, vip_next);
1759                         if (ip->vip_state != NODE_STATE_STALE)
1760                                 continue;
1761 
1762                         /* LINTED E_CONSTANT_CONDITION */
1763                         VRRPADDR2STR(af, &ip->vip_addr, abuf, INET6_ADDRSTRLEN,
1764                             _B_FALSE);
1765                         vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): IP %s "
1766                             "is removed over %s", abuf, intf->vvi_ifname);
1767                         vrrpd_delete_ip(intf, ip);
1768                 }
1769 
1770                 /*
1771                  * No IP addresses left, delete this interface.
1772                  */
1773                 if (TAILQ_EMPTY(&intf->vvi_iplist)) {
1774                         vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): "
1775                             "no IP left over %s", intf->vvi_ifname);
1776                         vrrpd_delete_if(intf, _B_TRUE);
1777                         continue;
1778                 }
1779 
1780                 /*
1781                  * If this is selected ss the physical interface for any
1782                  * VRRP router, reselect the primary address if needed.
1783                  */
1784                 if (IS_PRIMARY_INTF(intf)) {
1785                         vrrpd_reselect_primary(intf);
1786                         primary_now_selected = (intf->vvi_pip != NULL);
1787 
1788                         /*
1789                          * Cannot find the new primary IP address.
1790                          */
1791                         if (primary_selected && !primary_now_selected) {
1792                                 vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache() "
1793                                     "reselect primary IP on %s failed",
1794                                     intf->vvi_ifname);
1795                                 vrrpd_remove_if(intf, _B_TRUE);
1796                         } else if (!primary_selected && primary_now_selected) {
1797                                 /*
1798                                  * The primary IP address is successfully
1799                                  * selected on the physical interfacew we
1800                                  * need to walk through all the VRRP routers
1801                                  * that is created on this physical interface
1802                                  * and see whether they can now be enabled.
1803                                  */
1804                                 need_reenable = _B_TRUE;
1805                         }
1806                 }
1807 
1808                 /*
1809                  * For every new virtual IP address, bring up/down it based
1810                  * on the state of VRRP router.
1811                  *
1812                  * Note that it is fine to not update the IP's vip_flags field
1813                  * even if vrrpd_virtualip_updateone() changed the address's
1814                  * up/down state, since the vip_flags field is only used for
1815                  * select primary IP address over a physical interface, and
1816                  * vrrpd_virtualip_updateone() only affects the virtual IP
1817                  * address's status.
1818                  */
1819                 for (ip = TAILQ_FIRST(&intf->vvi_iplist); ip != NULL;
1820                     ip = nextip) {
1821                         nextip = TAILQ_NEXT(ip, vip_next);
1822                         /* LINTED E_CONSTANT_CONDITION */
1823                         VRRPADDR2STR(af, &ip->vip_addr, abuf, INET6_ADDRSTRLEN,
1824                             _B_FALSE);
1825                         vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): "
1826                             "IP %s over %s%s", abuf, intf->vvi_ifname,
1827                             ip->vip_state == NODE_STATE_NEW ? " is new" : "");
1828 
1829                         if (IS_VIRTUAL_INTF(intf)) {
1830                                 /*
1831                                  * If this IP is new, update its up/down state
1832                                  * based on the virtual interface's state
1833                                  * (which is determined by the VRRP router's
1834                                  * state). Otherwise, check only and prompt
1835                                  * warnings if its up/down state has been
1836                                  * changed.
1837                                  */
1838                                 if (vrrpd_virtualip_updateone(intf, ip,
1839                                     ip->vip_state == NODE_STATE_NONE) !=
1840                                     VRRP_SUCCESS) {
1841                                         vrrp_log(VRRP_DBG0,
1842                                             "vrrpd_update_ipcache(): "
1843                                             "IP %s over %s update failed", abuf,
1844                                             intf->vvi_ifname);
1845                                         vrrpd_delete_ip(intf, ip);
1846                                         continue;
1847                                 }
1848                         }
1849                         ip->vip_state = NODE_STATE_NONE;
1850                 }
1851 
1852                 /*
1853                  * The IP address is deleted when it is failed to be brought
1854                  * up. If no IP addresses are left, delete this interface.
1855                  */
1856                 if (TAILQ_EMPTY(&intf->vvi_iplist)) {
1857                         vrrp_log(VRRP_DBG0, "vrrpd_update_ipcache(): "
1858                             "no IP left over %s", intf->vvi_ifname);
1859                         vrrpd_delete_if(intf, _B_TRUE);
1860                         continue;
1861                 }
1862 
1863                 if (intf->vvi_state == NODE_STATE_NEW) {
1864                         /*
1865                          * A new interface is found. This interface can be
1866                          * the primary interface or the virtual VNIC
1867                          * interface.  Again, we need to walk throught all
1868                          * the VRRP routers to see whether some of them can
1869                          * now be enabled because of the new primary IP
1870                          * address or the new virtual IP addresses.
1871                          */
1872                         intf->vvi_state = NODE_STATE_NONE;
1873                         need_reenable = _B_TRUE;
1874                 }
1875         }
1876 
1877         if (need_reenable)
1878                 vrrpd_reenable_all_vr();
1879 }
1880 
1881 /*
1882  * Reselect primary IP if:
1883  * - The existing primary IP is no longer qualified (removed or it is down or
1884  *   not a link-local IP for IPv6 VRRP router);
1885  * - This is a physical interface but no primary IP is chosen;
1886  */
1887 static void
1888 vrrpd_reselect_primary(vrrp_intf_t *intf)
1889 {
1890         vrrp_ip_t       *ip;
1891         char            abuf[INET6_ADDRSTRLEN];
1892 
1893         assert(IS_PRIMARY_INTF(intf));
1894 
1895         /*
1896          * If the interface's old primary IP address is still valid, return
1897          */
1898         if (((ip = intf->vvi_pip) != NULL) && (QUALIFY_PRIMARY_ADDR(intf, ip)))
1899                 return;
1900 
1901         if (ip != NULL) {
1902                 /* LINTED E_CONSTANT_CONDITION */
1903                 VRRPADDR2STR(intf->vvi_af, &ip->vip_addr, abuf,
1904                     sizeof (abuf), _B_FALSE);
1905                 vrrp_log(VRRP_DBG0, "vrrpd_reselect_primary(%s): primary IP %s "
1906                     "is no longer qualified", intf->vvi_ifname, abuf);
1907         }
1908 
1909         ip = vrrpd_select_primary(intf);
1910         intf->vvi_pip = ip;
1911 
1912         if (ip != NULL) {
1913                 /* LINTED E_CONSTANT_CONDITION */
1914                 VRRPADDR2STR(intf->vvi_af, &ip->vip_addr, abuf,
1915                     sizeof (abuf), _B_FALSE);
1916                 vrrp_log(VRRP_DBG0, "vrrpd_reselect_primary(%s): primary IP %s "
1917                     "is selected", intf->vvi_ifname, abuf);
1918         }
1919 }
1920 
1921 /*
1922  * Select the primary IP address. Since the link-local IP address is always
1923  * at the head of the IP address list, try to find the first UP IP address
1924  * and see whether it qualify.
1925  */
1926 static vrrp_ip_t *
1927 vrrpd_select_primary(vrrp_intf_t *pif)
1928 {
1929         vrrp_ip_t       *pip;
1930         char            abuf[INET6_ADDRSTRLEN];
1931 
1932         vrrp_log(VRRP_DBG1, "vrrpd_select_primary(%s)", pif->vvi_ifname);
1933 
1934         TAILQ_FOREACH(pip, &pif->vvi_iplist, vip_next) {
1935                 assert(pip->vip_state != NODE_STATE_STALE);
1936 
1937                 /* LINTED E_CONSTANT_CONDITION */
1938                 VRRPADDR2STR(pif->vvi_af, &pip->vip_addr, abuf,
1939                     INET6_ADDRSTRLEN, _B_FALSE);
1940                 vrrp_log(VRRP_DBG0, "vrrpd_select_primary(%s): %s is %s",
1941                     pif->vvi_ifname, abuf,
1942                     (pip->vip_flags & IFF_UP) ? "up" : "down");
1943 
1944                 if (pip->vip_flags & IFF_UP)
1945                         break;
1946         }
1947 
1948         /*
1949          * Is this valid primary IP address?
1950          */
1951         if (pip == NULL || !QUALIFY_PRIMARY_ADDR(pif, pip)) {
1952                 vrrp_log(VRRP_DBG0, "vrrpd_select_primary(%s/%s) failed",
1953                     pif->vvi_ifname, af_str(pif->vvi_af));
1954                 return (NULL);
1955         }
1956         return (pip);
1957 }
1958 
1959 /*
1960  * This is a new interface. Check whether any VRRP router is waiting for it
1961  */
1962 static void
1963 vrrpd_reenable_all_vr()
1964 {
1965         vrrp_vr_t *vr;
1966 
1967         vrrp_log(VRRP_DBG0, "vrrpd_reenable_all_vr()");
1968 
1969         TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
1970                 if (vr->vvr_conf.vvc_enabled)
1971                         (void) vrrpd_enable_vr(vr);
1972         }
1973 }
1974 
1975 /*
1976  * If primary_addr_gone is _B_TRUE, it means that we failed to select
1977  * the primary IP address on this (physical) interface; otherwise,
1978  * it means the interface is no longer available.
1979  */
1980 static void
1981 vrrpd_remove_if(vrrp_intf_t *intf, boolean_t primary_addr_gone)
1982 {
1983         vrrp_vr_t *vr;
1984 
1985         vrrp_log(VRRP_DBG0, "vrrpd_remove_if(%s): %s", intf->vvi_ifname,
1986             primary_addr_gone ? "primary address gone" : "interface deleted");
1987 
1988         TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
1989                 if (vr->vvr_conf.vvc_enabled)
1990                         vrrpd_disable_vr(vr, intf, primary_addr_gone);
1991         }
1992 }
1993 
1994 /*
1995  * Update the VRRP configuration file based on the given configuration.
1996  * op is either VRRP_CONF_UPDATE or VRRP_CONF_DELETE
1997  */
1998 static vrrp_err_t
1999 vrrpd_updateconf(vrrp_vr_conf_t *newconf, uint_t op)
2000 {
2001         vrrp_vr_conf_t  conf;
2002         FILE            *fp, *nfp;
2003         int             nfd;
2004         char            line[LINE_MAX];
2005         char            newfile[MAXPATHLEN];
2006         boolean_t       found = _B_FALSE;
2007         vrrp_err_t      err = VRRP_SUCCESS;
2008 
2009         vrrp_log(VRRP_DBG0, "vrrpd_updateconf(%s, %s)", newconf->vvc_name,
2010             op == VRRP_CONF_UPDATE ? "update" : "delete");
2011 
2012         if ((fp = fopen(vrrpd_conffile, "r+F")) == NULL) {
2013                 if (errno != ENOENT) {
2014                         vrrp_log(VRRP_ERR, "vrrpd_updateconf(): open %s for "
2015                             "update failed: %s", vrrpd_conffile,
2016                             strerror(errno));
2017                         return (VRRP_EDB);
2018                 }
2019 
2020                 if ((fp = fopen(vrrpd_conffile, "w+F")) == NULL) {
2021                         vrrp_log(VRRP_ERR, "vrrpd_updateconf(): open %s for "
2022                             "write failed: %s", vrrpd_conffile,
2023                             strerror(errno));
2024                         return (VRRP_EDB);
2025                 }
2026         }
2027 
2028         (void) snprintf(newfile, MAXPATHLEN, "%s.new", vrrpd_conffile);
2029         if ((nfd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC,
2030             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
2031                 vrrp_log(VRRP_ERR, "vrrpd_updateconf(): open %s failed: %s",
2032                     newfile, strerror(errno));
2033                 (void) fclose(fp);
2034                 return (VRRP_EDB);
2035         }
2036 
2037         if ((nfp = fdopen(nfd, "wF")) == NULL) {
2038                 vrrp_log(VRRP_ERR, "vrrpd_updateconf(): fdopen(%s) failed: %s",
2039                     newfile, strerror(errno));
2040                 goto done;
2041         }
2042 
2043         while (fgets(line, sizeof (line), fp) != NULL) {
2044                 conf.vvc_vrid = VRRP_VRID_NONE;
2045                 if (!found && (err = vrrpd_read_vrconf(line, &conf)) !=
2046                     VRRP_SUCCESS) {
2047                         vrrp_log(VRRP_ERR, "vrrpd_updateconf(): invalid "
2048                             "configuration format: %s", line);
2049                         goto done;
2050                 }
2051 
2052                 /*
2053                  * Write this line out if:
2054                  * - this is a comment line; or
2055                  * - we've done updating/deleting the the given VR; or
2056                  * - if the name of the VR read from this line does not match
2057                  *   the VR name that we are about to update/delete;
2058                  */
2059                 if (found || conf.vvc_vrid == VRRP_VRID_NONE ||
2060                     strcmp(conf.vvc_name, newconf->vvc_name) != 0) {
2061                         if (fputs(line, nfp) != EOF)
2062                                 continue;
2063 
2064                         vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
2065                             "write line %s", line);
2066                         err = VRRP_EDB;
2067                         goto done;
2068                 }
2069 
2070                 /*
2071                  * Otherwise, update/skip the line.
2072                  */
2073                 found = _B_TRUE;
2074                 if (op == VRRP_CONF_DELETE)
2075                         continue;
2076 
2077                 assert(op == VRRP_CONF_UPDATE);
2078                 if ((err = vrrpd_write_vrconf(line, sizeof (line),
2079                     newconf)) != VRRP_SUCCESS) {
2080                         vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
2081                             "update configuration for %s", newconf->vvc_name);
2082                         goto done;
2083                 }
2084                 if (fputs(line, nfp) == EOF) {
2085                         vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
2086                             "write line %s", line);
2087                         err = VRRP_EDB;
2088                         goto done;
2089                 }
2090         }
2091 
2092         /*
2093          * If we get to the end of the file and have not seen the router that
2094          * we are about to update, write it out.
2095          */
2096         if (!found && op == VRRP_CONF_UPDATE) {
2097                 if ((err = vrrpd_write_vrconf(line, sizeof (line),
2098                     newconf)) == VRRP_SUCCESS && fputs(line, nfp) == EOF) {
2099                         vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
2100                             "write line %s", line);
2101                         err = VRRP_EDB;
2102                 }
2103         } else if (!found && op == VRRP_CONF_DELETE) {
2104                 vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to find "
2105                     "configuation for %s", newconf->vvc_name);
2106                 err = VRRP_ENOTFOUND;
2107         }
2108 
2109         if (err != VRRP_SUCCESS)
2110                 goto done;
2111 
2112         if (fflush(nfp) == EOF || rename(newfile, vrrpd_conffile) < 0) {
2113                 vrrp_log(VRRP_ERR, "vrrpd_updateconf(): failed to "
2114                     "rename file %s", newfile);
2115                 err = VRRP_EDB;
2116         }
2117 
2118 done:
2119         (void) fclose(fp);
2120         (void) fclose(nfp);
2121         (void) unlink(newfile);
2122         return (err);
2123 }
2124 
2125 static vrrp_err_t
2126 vrrpd_write_vrconf(char *line, size_t len, vrrp_vr_conf_t *conf)
2127 {
2128         vrrp_prop_t     *prop;
2129         int             n, i;
2130 
2131         vrrp_log(VRRP_DBG0, "vrrpd_write_vrconf(%s)", conf->vvc_name);
2132 
2133         for (i = 0; i < VRRP_PROP_INFO_TABSIZE; i++) {
2134                 prop = &vrrp_prop_info_tbl[i];
2135                 n = snprintf(line, len, i == 0 ? "%s=" : " %s=",
2136                     prop->vs_propname);
2137                 if (n < 0 || n >= len)
2138                         break;
2139                 len -= n;
2140                 line += n;
2141                 n = prop->vs_propwrite(conf, line, len);
2142                 if (n < 0 || n >= len)
2143                         break;
2144                 len -= n;
2145                 line += n;
2146         }
2147         if (i != VRRP_PROP_INFO_TABSIZE) {
2148                 vrrp_log(VRRP_ERR, "vrrpd_write_vrconf(%s): buffer size too"
2149                     "small", conf->vvc_name);
2150                 return (VRRP_EDB);
2151         }
2152         n = snprintf(line, len, "\n");
2153         if (n < 0 || n >= len) {
2154                 vrrp_log(VRRP_ERR, "vrrpd_write_vrconf(%s): buffer size too"
2155                     "small", conf->vvc_name);
2156                 return (VRRP_EDB);
2157         }
2158         return (VRRP_SUCCESS);
2159 }
2160 
2161 static vrrp_err_t
2162 vrrpd_read_vrconf(char *line, vrrp_vr_conf_t *conf)
2163 {
2164         char            *str, *token;
2165         char            *next;
2166         vrrp_err_t      err = VRRP_SUCCESS;
2167         char            tmpbuf[MAXLINELEN];
2168 
2169         str = tmpbuf;
2170         (void) strlcpy(tmpbuf, line, MAXLINELEN);
2171 
2172         /*
2173          * Skip leading spaces, blank lines, and comments.
2174          */
2175         skip_whitespace(str);
2176         if ((str - tmpbuf == strlen(tmpbuf)) || (*str == '#')) {
2177                 conf->vvc_vrid = VRRP_VRID_NONE;
2178                 return (VRRP_SUCCESS);
2179         }
2180 
2181         /*
2182          * Read each VR properties.
2183          */
2184         for (token = strtok_r(str, " \n\t", &next); token != NULL;
2185             token = strtok_r(NULL, " \n\t", &next)) {
2186                 if ((err = vrrpd_readprop(token, conf)) != VRRP_SUCCESS)
2187                         break;
2188         }
2189 
2190         /* All properties read but no VRID defined */
2191         if (err == VRRP_SUCCESS && conf->vvc_vrid == VRRP_VRID_NONE)
2192                 err = VRRP_EINVAL;
2193 
2194         return (err);
2195 }
2196 
2197 static vrrp_err_t
2198 vrrpd_readprop(const char *str, vrrp_vr_conf_t *conf)
2199 {
2200         vrrp_prop_t     *prop;
2201         char            *pstr;
2202         int             i;
2203 
2204         if ((pstr = strchr(str, '=')) == NULL) {
2205                 vrrp_log(VRRP_ERR, "vrrpd_readprop(%s): invalid property", str);
2206                 return (VRRP_EINVAL);
2207         }
2208 
2209         *pstr++ = '\0';
2210         for (i = 0; i < VRRP_PROP_INFO_TABSIZE; i++) {
2211                 prop = &vrrp_prop_info_tbl[i];
2212                 if (strcasecmp(str, prop->vs_propname) == 0) {
2213                         if (prop->vs_propread(conf, pstr))
2214                                 break;
2215                 }
2216         }
2217 
2218         if (i == VRRP_PROP_INFO_TABSIZE) {
2219                 vrrp_log(VRRP_ERR, "vrrpd_readprop(%s): invalid property", str);
2220                 return (VRRP_EINVAL);
2221         }
2222 
2223         return (VRRP_SUCCESS);
2224 }
2225 
2226 static boolean_t
2227 vrrp_rd_prop_name(vrrp_vr_conf_t *conf, const char *str)
2228 {
2229         size_t size = sizeof (conf->vvc_name);
2230         return (strlcpy(conf->vvc_name, str, size) < size);
2231 }
2232 
2233 static boolean_t
2234 vrrp_rd_prop_vrid(vrrp_vr_conf_t *conf, const char *str)
2235 {
2236         conf->vvc_vrid = strtol(str, NULL, 0);
2237         return (!(conf->vvc_vrid < VRRP_VRID_MIN ||
2238             conf->vvc_vrid > VRRP_VRID_MAX ||
2239             (conf->vvc_vrid == 0 && errno != 0)));
2240 }
2241 
2242 static boolean_t
2243 vrrp_rd_prop_af(vrrp_vr_conf_t *conf, const char *str)
2244 {
2245         if (strcasecmp(str, "AF_INET") == 0)
2246                 conf->vvc_af = AF_INET;
2247         else if (strcasecmp(str, "AF_INET6") == 0)
2248                 conf->vvc_af = AF_INET6;
2249         else
2250                 return (_B_FALSE);
2251         return (_B_TRUE);
2252 }
2253 
2254 static boolean_t
2255 vrrp_rd_prop_pri(vrrp_vr_conf_t *conf, const char *str)
2256 {
2257         conf->vvc_pri = strtol(str, NULL, 0);
2258         return (!(conf->vvc_pri < VRRP_PRI_MIN ||
2259             conf->vvc_pri > VRRP_PRI_OWNER ||
2260             (conf->vvc_pri == 0 && errno != 0)));
2261 }
2262 
2263 static boolean_t
2264 vrrp_rd_prop_adver_int(vrrp_vr_conf_t *conf, const char *str)
2265 {
2266         conf->vvc_adver_int = strtol(str, NULL, 0);
2267         return (!(conf->vvc_adver_int < VRRP_MAX_ADVER_INT_MIN ||
2268             conf->vvc_adver_int > VRRP_MAX_ADVER_INT_MAX ||
2269             (conf->vvc_adver_int == 0 && errno != 0)));
2270 }
2271 
2272 static boolean_t
2273 vrrp_rd_prop_preempt(vrrp_vr_conf_t *conf, const char *str)
2274 {
2275         if (strcasecmp(str, "true") == 0)
2276                 conf->vvc_preempt = _B_TRUE;
2277         else if (strcasecmp(str, "false") == 0)
2278                 conf->vvc_preempt = _B_FALSE;
2279         else
2280                 return (_B_FALSE);
2281         return (_B_TRUE);
2282 }
2283 
2284 static boolean_t
2285 vrrp_rd_prop_accept(vrrp_vr_conf_t *conf, const char *str)
2286 {
2287         if (strcasecmp(str, "true") == 0)
2288                 conf->vvc_accept = _B_TRUE;
2289         else if (strcasecmp(str, "false") == 0)
2290                 conf->vvc_accept = _B_FALSE;
2291         else
2292                 return (_B_FALSE);
2293         return (_B_TRUE);
2294 }
2295 
2296 static boolean_t
2297 vrrp_rd_prop_enabled(vrrp_vr_conf_t *conf, const char *str)
2298 {
2299         if (strcasecmp(str, "enabled") == 0)
2300                 conf->vvc_enabled = _B_TRUE;
2301         else if (strcasecmp(str, "disabled") == 0)
2302                 conf->vvc_enabled = _B_FALSE;
2303         else
2304                 return (_B_FALSE);
2305         return (_B_TRUE);
2306 }
2307 
2308 static boolean_t
2309 vrrp_rd_prop_ifname(vrrp_vr_conf_t *conf, const char *str)
2310 {
2311         size_t size = sizeof (conf->vvc_link);
2312         return (strlcpy(conf->vvc_link, str, size) < size);
2313 }
2314 
2315 static int
2316 vrrp_wt_prop_name(vrrp_vr_conf_t *conf, char *str, size_t size)
2317 {
2318         return (snprintf(str, size, "%s", conf->vvc_name));
2319 }
2320 
2321 static int
2322 vrrp_wt_prop_pri(vrrp_vr_conf_t *conf, char *str, size_t size)
2323 {
2324         return (snprintf(str, size, "%d", conf->vvc_pri));
2325 }
2326 
2327 static int
2328 vrrp_wt_prop_adver_int(vrrp_vr_conf_t *conf, char *str, size_t size)
2329 {
2330         return (snprintf(str, size, "%d", conf->vvc_adver_int));
2331 }
2332 
2333 static int
2334 vrrp_wt_prop_preempt(vrrp_vr_conf_t *conf, char *str, size_t size)
2335 {
2336         return (snprintf(str, size, "%s",
2337             conf->vvc_preempt ? "true" : "false"));
2338 }
2339 
2340 static int
2341 vrrp_wt_prop_accept(vrrp_vr_conf_t *conf, char *str, size_t size)
2342 {
2343         return (snprintf(str, size, "%s",
2344             conf->vvc_accept ? "true" : "false"));
2345 }
2346 
2347 static int
2348 vrrp_wt_prop_enabled(vrrp_vr_conf_t *conf, char *str, size_t size)
2349 {
2350         return (snprintf(str, size, "%s",
2351             conf->vvc_enabled ? "enabled" : "disabled"));
2352 }
2353 
2354 static int
2355 vrrp_wt_prop_vrid(vrrp_vr_conf_t *conf, char *str, size_t size)
2356 {
2357         return (snprintf(str, size, "%d", conf->vvc_vrid));
2358 }
2359 
2360 static int
2361 vrrp_wt_prop_af(vrrp_vr_conf_t *conf, char *str, size_t size)
2362 {
2363         return (snprintf(str, size, "%s",
2364             conf->vvc_af == AF_INET ? "AF_INET" : "AF_INET6"));
2365 }
2366 
2367 static int
2368 vrrp_wt_prop_ifname(vrrp_vr_conf_t *conf, char *str, size_t size)
2369 {
2370         return (snprintf(str, size, "%s", conf->vvc_link));
2371 }
2372 
2373 static char *
2374 af_str(int af)
2375 {
2376         if (af == 4 || af == AF_INET)
2377                 return ("AF_INET");
2378         else if (af == 6 || af == AF_INET6)
2379                 return ("AF_INET6");
2380         else if (af == AF_UNSPEC)
2381                 return ("AF_UNSPEC");
2382         else
2383                 return ("AF_error");
2384 }
2385 
2386 static vrrp_err_t
2387 vrrpd_create_vr(vrrp_vr_conf_t *conf)
2388 {
2389         vrrp_vr_t       *vr;
2390 
2391         vrrp_log(VRRP_DBG0, "vrrpd_create_vr(%s)", conf->vvc_name);
2392 
2393         if ((vr = malloc(sizeof (vrrp_vr_t))) == NULL) {
2394                 vrrp_log(VRRP_ERR, "vrrpd_create_vr(): memory allocation for %s"
2395                     " failed", conf->vvc_name);
2396                 return (VRRP_ENOMEM);
2397         }
2398 
2399         bzero(vr, sizeof (vrrp_vr_t));
2400         vr->vvr_state = VRRP_STATE_NONE;
2401         vr->vvr_timer_id = -1;
2402         vrrpd_state_trans(VRRP_STATE_NONE, VRRP_STATE_INIT, vr);
2403         (void) memcpy(&vr->vvr_conf, conf, sizeof (vrrp_vr_conf_t));
2404         vr->vvr_conf.vvc_enabled = _B_FALSE;
2405         TAILQ_INSERT_HEAD(&vrrp_vr_list, vr, vvr_next);
2406         return (VRRP_SUCCESS);
2407 }
2408 
2409 static void
2410 vrrpd_delete_vr(vrrp_vr_t *vr)
2411 {
2412         vrrp_log(VRRP_DBG0, "vrrpd_delete_vr(%s)", vr->vvr_conf.vvc_name);
2413         if (vr->vvr_conf.vvc_enabled)
2414                 vrrpd_disable_vr(vr, NULL, _B_FALSE);
2415         assert(vr->vvr_state == VRRP_STATE_INIT);
2416         vrrpd_state_trans(VRRP_STATE_INIT, VRRP_STATE_NONE, vr);
2417         TAILQ_REMOVE(&vrrp_vr_list, vr, vvr_next);
2418         (void) free(vr);
2419 }
2420 
2421 static vrrp_err_t
2422 vrrpd_enable_vr(vrrp_vr_t *vr)
2423 {
2424         vrrp_err_t      rx_err, tx_err, err = VRRP_EINVAL;
2425 
2426         vrrp_log(VRRP_DBG0, "vrrpd_enable_vr(%s)", vr->vvr_conf.vvc_name);
2427 
2428         assert(vr->vvr_conf.vvc_enabled);
2429 
2430         /*
2431          * This VRRP router has been successfully enabled and start
2432          * participating.
2433          */
2434         if (vr->vvr_state != VRRP_STATE_INIT)
2435                 return (VRRP_SUCCESS);
2436 
2437         if ((rx_err = vrrpd_init_rxsock(vr)) == VRRP_SUCCESS) {
2438                 /*
2439                  * Select the primary IP address. Even if this time
2440                  * primary IP selection failed, we will reselect the
2441                  * primary IP address when new IP address comes up.
2442                  */
2443                 vrrpd_reselect_primary(vr->vvr_pif);
2444                 if (vr->vvr_pif->vvi_pip == NULL) {
2445                         vrrp_log(VRRP_DBG0, "vrrpd_enable_vr(%s): "
2446                             "select_primary over %s failed",
2447                             vr->vvr_conf.vvc_name, vr->vvr_pif->vvi_ifname);
2448                         rx_err = VRRP_ENOPRIM;
2449                 }
2450         }
2451 
2452         /*
2453          * Initialize the TX socket used for this vrrp_vr_t to send the
2454          * multicast packets.
2455          */
2456         tx_err = vrrpd_init_txsock(vr);
2457 
2458         /*
2459          * Only start the state transition if sockets for both RX and TX are
2460          * initialized correctly.
2461          */
2462         if (rx_err != VRRP_SUCCESS || tx_err != VRRP_SUCCESS) {
2463                 /*
2464                  * Record the error information for diagnose purpose.
2465                  */
2466                 vr->vvr_err = (rx_err == VRRP_SUCCESS) ? tx_err : rx_err;
2467                 return (err);
2468         }
2469 
2470         if (vr->vvr_conf.vvc_pri == 255)
2471                 err = vrrpd_state_i2m(vr);
2472         else
2473                 err = vrrpd_state_i2b(vr);
2474 
2475         if (err != VRRP_SUCCESS) {
2476                 vr->vvr_err = err;
2477                 vr->vvr_pif->vvi_pip = NULL;
2478                 vrrpd_fini_txsock(vr);
2479                 vrrpd_fini_rxsock(vr);
2480         }
2481         return (err);
2482 }
2483 
2484 /*
2485  * Given the removed interface, see whether the given VRRP router would
2486  * be affected and stop participating the VRRP protocol.
2487  *
2488  * If intf is NULL, VR disabling request is coming from the admin.
2489  */
2490 static void
2491 vrrpd_disable_vr(vrrp_vr_t *vr, vrrp_intf_t *intf, boolean_t primary_addr_gone)
2492 {
2493         vrrp_log(VRRP_DBG0, "vrrpd_disable_vr(%s): %s%s", vr->vvr_conf.vvc_name,
2494             intf == NULL ? "requested by admin" : intf->vvi_ifname,
2495             intf == NULL ? "" : (primary_addr_gone ? "primary address gone" :
2496             "interface deleted"));
2497 
2498         /*
2499          * An interface is deleted, see whether this interface is the
2500          * physical interface or the VNIC of the given VRRP router.
2501          * If so, continue to disable the VRRP router.
2502          */
2503         if (!primary_addr_gone && (intf != NULL) && (intf != vr->vvr_pif) &&
2504             (intf != vr->vvr_vif)) {
2505                 return;
2506         }
2507 
2508         /*
2509          * If this is the case that the primary IP address is gone,
2510          * and we failed to reselect another primary IP address,
2511          * continue to disable the VRRP router.
2512          */
2513         if (primary_addr_gone && intf != vr->vvr_pif)
2514                 return;
2515 
2516         vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): disabling",
2517             vr->vvr_conf.vvc_name);
2518 
2519         if (vr->vvr_state == VRRP_STATE_MASTER) {
2520                 /*
2521                  * If this router is disabled by the administrator, send
2522                  * the zero-priority advertisement to indicate the Master
2523                  * stops participating VRRP.
2524                  */
2525                 if (intf == NULL)
2526                         (void) vrrpd_send_adv(vr, _B_TRUE);
2527 
2528                 vrrpd_state_m2i(vr);
2529         } else  if (vr->vvr_state == VRRP_STATE_BACKUP) {
2530                 vrrpd_state_b2i(vr);
2531         }
2532 
2533         /*
2534          * If no primary IP address can be selected, the VRRP router
2535          * stays at the INIT state and will become BACKUP and MASTER when
2536          * a primary IP address is reselected.
2537          */
2538         if (primary_addr_gone) {
2539                 vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): primary IP "
2540                     "is removed", vr->vvr_conf.vvc_name);
2541                 vr->vvr_err = VRRP_ENOPRIM;
2542         } else if (intf == NULL) {
2543                 /*
2544                  * The VRRP router is disable by the administrator
2545                  */
2546                 vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): disabled by admin",
2547                     vr->vvr_conf.vvc_name);
2548                 vr->vvr_err = VRRP_SUCCESS;
2549                 vrrpd_fini_txsock(vr);
2550                 vrrpd_fini_rxsock(vr);
2551         } else if (intf == vr->vvr_pif) {
2552                 vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): physical interface "
2553                     "%s removed", vr->vvr_conf.vvc_name, intf->vvi_ifname);
2554                 vr->vvr_err = VRRP_ENOPRIM;
2555                 vrrpd_fini_rxsock(vr);
2556         } else if (intf == vr->vvr_vif) {
2557                 vrrp_log(VRRP_DBG1, "vrrpd_disable_vr(%s): VNIC interface %s"
2558                     " removed", vr->vvr_conf.vvc_name, intf->vvi_ifname);
2559                 vr->vvr_err = VRRP_ENOVIRT;
2560                 vrrpd_fini_txsock(vr);
2561         }
2562 }
2563 
2564 vrrp_err_t
2565 vrrpd_create(vrrp_vr_conf_t *conf, boolean_t updateconf)
2566 {
2567         vrrp_err_t      err = VRRP_SUCCESS;
2568 
2569         vrrp_log(VRRP_DBG0, "vrrpd_create(%s, %s, %d)", conf->vvc_name,
2570             conf->vvc_link, conf->vvc_vrid);
2571 
2572         assert(conf != NULL);
2573 
2574         /*
2575          * Sanity check
2576          */
2577         if ((strlen(conf->vvc_name) == 0) ||
2578             (strlen(conf->vvc_link) == 0) ||
2579             (conf->vvc_vrid < VRRP_VRID_MIN ||
2580             conf->vvc_vrid > VRRP_VRID_MAX) ||
2581             (conf->vvc_pri < VRRP_PRI_MIN ||
2582             conf->vvc_pri > VRRP_PRI_OWNER) ||
2583             (conf->vvc_adver_int < VRRP_MAX_ADVER_INT_MIN ||
2584             conf->vvc_adver_int > VRRP_MAX_ADVER_INT_MAX) ||
2585             (conf->vvc_af != AF_INET && conf->vvc_af != AF_INET6) ||
2586             (conf->vvc_pri == VRRP_PRI_OWNER && !conf->vvc_accept)) {
2587                 vrrp_log(VRRP_DBG1, "vrrpd_create(%s): invalid argument",
2588                     conf->vvc_name);
2589                 return (VRRP_EINVAL);
2590         }
2591 
2592         if (!vrrp_valid_name(conf->vvc_name)) {
2593                 vrrp_log(VRRP_DBG1, "vrrpd_create(): %s is not a valid router "
2594                     "name", conf->vvc_name);
2595                 return (VRRP_EINVALVRNAME);
2596         }
2597 
2598         if (vrrpd_lookup_vr_by_name(conf->vvc_name) != NULL) {
2599                 vrrp_log(VRRP_DBG1, "vrrpd_create(): %s already exists",
2600                     conf->vvc_name);
2601                 return (VRRP_EINSTEXIST);
2602         }
2603 
2604         if (vrrpd_lookup_vr_by_vrid(conf->vvc_link, conf->vvc_vrid,
2605             conf->vvc_af) != NULL) {
2606                 vrrp_log(VRRP_DBG1, "vrrpd_create(): VRID %d/%s over %s "
2607                     "already exists", conf->vvc_vrid, af_str(conf->vvc_af),
2608                     conf->vvc_link);
2609                 return (VRRP_EVREXIST);
2610         }
2611 
2612         if (updateconf && (err = vrrpd_updateconf(conf,
2613             VRRP_CONF_UPDATE)) != VRRP_SUCCESS) {
2614                 vrrp_log(VRRP_ERR, "vrrpd_create(): failed to update "
2615                     "configuration for %s", conf->vvc_name);
2616                 return (err);
2617         }
2618 
2619         err = vrrpd_create_vr(conf);
2620         if (err != VRRP_SUCCESS && updateconf)
2621                 (void) vrrpd_updateconf(conf, VRRP_CONF_DELETE);
2622 
2623         return (err);
2624 }
2625 
2626 static vrrp_err_t
2627 vrrpd_delete(const char *vn)
2628 {
2629         vrrp_vr_t       *vr;
2630         vrrp_err_t      err;
2631 
2632         vrrp_log(VRRP_DBG0, "vrrpd_delete(%s)", vn);
2633 
2634         if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
2635                 vrrp_log(VRRP_DBG1, "vrrpd_delete(): %s not exists", vn);
2636                 return (VRRP_ENOTFOUND);
2637         }
2638 
2639         err = vrrpd_updateconf(&vr->vvr_conf, VRRP_CONF_DELETE);
2640         if (err != VRRP_SUCCESS) {
2641                 vrrp_log(VRRP_ERR, "vrrpd_delete(): failed to delete "
2642                     "configuration for %s", vr->vvr_conf.vvc_name);
2643                 return (err);
2644         }
2645 
2646         vrrpd_delete_vr(vr);
2647         return (VRRP_SUCCESS);
2648 }
2649 
2650 static vrrp_err_t
2651 vrrpd_enable(const char *vn, boolean_t updateconf)
2652 {
2653         vrrp_vr_t               *vr;
2654         vrrp_vr_conf_t          *conf;
2655         uint32_t                flags;
2656         datalink_class_t        class;
2657         vrrp_err_t              err = VRRP_SUCCESS;
2658 
2659         vrrp_log(VRRP_DBG0, "vrrpd_enable(%s)", vn);
2660 
2661         if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
2662                 vrrp_log(VRRP_DBG1, "vrrpd_enable(): %s does not exist", vn);
2663                 return (VRRP_ENOTFOUND);
2664         }
2665 
2666         /*
2667          * The VR is already enabled.
2668          */
2669         conf = &vr->vvr_conf;
2670         if (conf->vvc_enabled) {
2671                 vrrp_log(VRRP_DBG1, "vrrpd_enable(): %s is already "
2672                     "enabled", vn);
2673                 return (VRRP_EALREADY);
2674         }
2675 
2676         /*
2677          * Check whether the link exists.
2678          */
2679         if ((strlen(conf->vvc_link) == 0) || dladm_name2info(vrrpd_vh->vh_dh,
2680             conf->vvc_link, NULL, &flags, &class, NULL) != DLADM_STATUS_OK ||
2681             !(flags & DLADM_OPT_ACTIVE) || ((class != DATALINK_CLASS_PHYS) &&
2682             (class != DATALINK_CLASS_VLAN) && (class != DATALINK_CLASS_AGGR) &&
2683             (class != DATALINK_CLASS_VNIC))) {
2684                 vrrp_log(VRRP_DBG1, "vrrpd_enable(%s): invalid link %s",
2685                     vn, conf->vvc_link);
2686                 return (VRRP_EINVALLINK);
2687         }
2688 
2689         /*
2690          * Get the associated VNIC name by the given interface/vrid/
2691          * address famitly.
2692          */
2693         err = vrrp_get_vnicname(vrrpd_vh, conf->vvc_vrid,
2694             conf->vvc_af, conf->vvc_link, NULL, NULL, vr->vvr_vnic,
2695             sizeof (vr->vvr_vnic));
2696         if (err != VRRP_SUCCESS) {
2697                 vrrp_log(VRRP_DBG1, "vrrpd_enable(%s): no VNIC for VRID %d/%s "
2698                     "over %s", vn, conf->vvc_vrid, af_str(conf->vvc_af),
2699                     conf->vvc_link);
2700                 err = VRRP_ENOVNIC;
2701                 goto fail;
2702         }
2703 
2704         /*
2705          * Find the right VNIC, primary interface and get the list of the
2706          * protected IP adressses and primary IP address. Note that if
2707          * either interface is NULL (no IP addresses configured over the
2708          * interface), we will still continue and mark this VRRP router
2709          * as "enabled".
2710          */
2711         vr->vvr_conf.vvc_enabled = _B_TRUE;
2712         if (updateconf && (err = vrrpd_updateconf(&vr->vvr_conf,
2713             VRRP_CONF_UPDATE)) != VRRP_SUCCESS) {
2714                 vrrp_log(VRRP_ERR, "vrrpd_enable(): failed to update "
2715                     "configuration for %s", vr->vvr_conf.vvc_name);
2716                 goto fail;
2717         }
2718 
2719         /*
2720          * If vrrpd_setup_vr() fails, it is possible that there is no IP
2721          * addresses over ether the primary interface or the VNIC yet,
2722          * return success in this case, the VRRP router will stay in
2723          * the initialized state and start to work when the IP address is
2724          * configured.
2725          */
2726         (void) vrrpd_enable_vr(vr);
2727         return (VRRP_SUCCESS);
2728 
2729 fail:
2730         vr->vvr_conf.vvc_enabled = _B_FALSE;
2731         vr->vvr_vnic[0] = '\0';
2732         return (err);
2733 }
2734 
2735 static vrrp_err_t
2736 vrrpd_disable(const char *vn)
2737 {
2738         vrrp_vr_t       *vr;
2739         vrrp_err_t      err;
2740 
2741         vrrp_log(VRRP_DBG0, "vrrpd_disable(%s)", vn);
2742 
2743         if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
2744                 vrrp_log(VRRP_DBG1, "vrrpd_disable(): %s does not exist", vn);
2745                 return (VRRP_ENOTFOUND);
2746         }
2747 
2748         /*
2749          * The VR is already disable.
2750          */
2751         if (!vr->vvr_conf.vvc_enabled) {
2752                 vrrp_log(VRRP_DBG1, "vrrpd_disable(): %s was not enabled", vn);
2753                 return (VRRP_EALREADY);
2754         }
2755 
2756         vr->vvr_conf.vvc_enabled = _B_FALSE;
2757         err = vrrpd_updateconf(&vr->vvr_conf, VRRP_CONF_UPDATE);
2758         if (err != VRRP_SUCCESS) {
2759                 vr->vvr_conf.vvc_enabled = _B_TRUE;
2760                 vrrp_log(VRRP_ERR, "vrrpd_disable(): failed to update "
2761                     "configuration for %s", vr->vvr_conf.vvc_name);
2762                 return (err);
2763         }
2764 
2765         vrrpd_disable_vr(vr, NULL, _B_FALSE);
2766         vr->vvr_vnic[0] = '\0';
2767         return (VRRP_SUCCESS);
2768 }
2769 
2770 static vrrp_err_t
2771 vrrpd_modify(vrrp_vr_conf_t *conf, uint32_t mask)
2772 {
2773         vrrp_vr_t       *vr;
2774         vrrp_vr_conf_t  savconf;
2775         int             pri;
2776         boolean_t       accept, set_accept = _B_FALSE;
2777         vrrp_err_t      err;
2778 
2779         vrrp_log(VRRP_DBG0, "vrrpd_modify(%s)", conf->vvc_name);
2780 
2781         if (mask == 0)
2782                 return (VRRP_SUCCESS);
2783 
2784         if ((vr = vrrpd_lookup_vr_by_name(conf->vvc_name)) == NULL) {
2785                 vrrp_log(VRRP_DBG1, "vrrpd_modify(): cannot find the given "
2786                     "VR instance: %s", conf->vvc_name);
2787                 return (VRRP_ENOTFOUND);
2788         }
2789 
2790         if (mask & VRRP_CONF_INTERVAL) {
2791                 if (conf->vvc_adver_int < VRRP_MAX_ADVER_INT_MIN ||
2792                     conf->vvc_adver_int > VRRP_MAX_ADVER_INT_MAX) {
2793                         vrrp_log(VRRP_DBG1, "vrrpd_modify(%s): invalid "
2794                             "adver_interval %d", conf->vvc_name,
2795                             conf->vvc_adver_int);
2796                         return (VRRP_EINVAL);
2797                 }
2798         }
2799 
2800         pri = vr->vvr_conf.vvc_pri;
2801         if (mask & VRRP_CONF_PRIORITY) {
2802                 if (conf->vvc_pri < VRRP_PRI_MIN ||
2803                     conf->vvc_pri > VRRP_PRI_OWNER) {
2804                         vrrp_log(VRRP_DBG1, "vrrpd_modify(%s): invalid "
2805                             "priority %d", conf->vvc_name, conf->vvc_pri);
2806                         return (VRRP_EINVAL);
2807                 }
2808                 pri = conf->vvc_pri;
2809         }
2810 
2811         accept = vr->vvr_conf.vvc_accept;
2812         if (mask & VRRP_CONF_ACCEPT)
2813                 accept = conf->vvc_accept;
2814 
2815         if (pri == VRRP_PRI_OWNER && !accept) {
2816                 vrrp_log(VRRP_DBG1, "vrrpd_modify(%s): accept mode must be "
2817                     "true for VRRP address owner", conf->vvc_name);
2818                 return (VRRP_EINVAL);
2819         }
2820 
2821         if ((mask & VRRP_CONF_ACCEPT) && (vr->vvr_conf.vvc_accept != accept)) {
2822                 err = vrrpd_set_noaccept(vr, !accept);
2823                 if (err != VRRP_SUCCESS) {
2824                         vrrp_log(VRRP_ERR, "vrrpd_modify(%s): access mode "
2825                             "updating failed: %s", conf->vvc_name,
2826                             vrrp_err2str(err));
2827                         return (err);
2828                 }
2829                 set_accept = _B_TRUE;
2830         }
2831 
2832         /*
2833          * Save the current configuration, so it can be restored if the
2834          * following fails.
2835          */
2836         (void) memcpy(&savconf, &vr->vvr_conf, sizeof (vrrp_vr_conf_t));
2837         if (mask & VRRP_CONF_PREEMPT)
2838                 vr->vvr_conf.vvc_preempt = conf->vvc_preempt;
2839 
2840         if (mask & VRRP_CONF_ACCEPT)
2841                 vr->vvr_conf.vvc_accept = accept;
2842 
2843         if (mask & VRRP_CONF_PRIORITY)
2844                 vr->vvr_conf.vvc_pri = pri;
2845 
2846         if (mask & VRRP_CONF_INTERVAL)
2847                 vr->vvr_conf.vvc_adver_int = conf->vvc_adver_int;
2848 
2849         err = vrrpd_updateconf(&vr->vvr_conf, VRRP_CONF_UPDATE);
2850         if (err != VRRP_SUCCESS) {
2851                 vrrp_log(VRRP_ERR, "vrrpd_modify(%s): configuration update "
2852                     "failed: %s", conf->vvc_name, vrrp_err2str(err));
2853                 if (set_accept)
2854                         (void) vrrpd_set_noaccept(vr, accept);
2855                 (void) memcpy(&vr->vvr_conf, &savconf, sizeof (vrrp_vr_conf_t));
2856                 return (err);
2857         }
2858 
2859         if ((mask & VRRP_CONF_PRIORITY) && (vr->vvr_state == VRRP_STATE_BACKUP))
2860                 vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
2861 
2862         if ((mask & VRRP_CONF_INTERVAL) && (vr->vvr_state == VRRP_STATE_MASTER))
2863                 vr->vvr_timeout = conf->vvc_adver_int;
2864 
2865         return (VRRP_SUCCESS);
2866 }
2867 
2868 static void
2869 vrrpd_list(vrid_t vrid, char *ifname, int af, vrrp_ret_list_t *ret,
2870     size_t *sizep)
2871 {
2872         vrrp_vr_t       *vr;
2873         char            *p = (char *)ret + sizeof (vrrp_ret_list_t);
2874         size_t          size = (*sizep) - sizeof (vrrp_ret_list_t);
2875 
2876         vrrp_log(VRRP_DBG0, "vrrpd_list(%d_%s_%s)", vrid, ifname, af_str(af));
2877 
2878         ret->vrl_cnt = 0;
2879         TAILQ_FOREACH(vr, &vrrp_vr_list, vvr_next) {
2880                 if (vrid !=  VRRP_VRID_NONE && vr->vvr_conf.vvc_vrid != vrid)
2881                         continue;
2882 
2883                 if (strlen(ifname) != 0 && strcmp(ifname,
2884                     vr->vvr_conf.vvc_link) == 0) {
2885                         continue;
2886                 }
2887 
2888                 if ((af == AF_INET || af == AF_INET6) &&
2889                     vr->vvr_conf.vvc_af != af)
2890                         continue;
2891 
2892                 if (size < VRRP_NAME_MAX) {
2893                         vrrp_log(VRRP_DBG1, "vrrpd_list(): buffer size too "
2894                             "small to hold %d router names", ret->vrl_cnt);
2895                         *sizep = sizeof (vrrp_ret_list_t);
2896                         ret->vrl_err = VRRP_ETOOSMALL;
2897                         return;
2898                 }
2899                 (void) strlcpy(p, vr->vvr_conf.vvc_name, VRRP_NAME_MAX);
2900                 p += (strlen(vr->vvr_conf.vvc_name) + 1);
2901                 ret->vrl_cnt++;
2902                 size -= VRRP_NAME_MAX;
2903         }
2904 
2905         *sizep = sizeof (vrrp_ret_list_t) + ret->vrl_cnt * VRRP_NAME_MAX;
2906         vrrp_log(VRRP_DBG1, "vrrpd_list() return %d", ret->vrl_cnt);
2907         ret->vrl_err = VRRP_SUCCESS;
2908 }
2909 
2910 static void
2911 vrrpd_query(const char *vn, vrrp_ret_query_t *ret, size_t *sizep)
2912 {
2913         vrrp_queryinfo_t        *infop;
2914         vrrp_vr_t               *vr;
2915         vrrp_intf_t             *vif;
2916         vrrp_ip_t               *ip;
2917         struct timeval          now;
2918         uint32_t                vipcnt = 0;
2919         size_t                  size = *sizep;
2920 
2921         vrrp_log(VRRP_DBG1, "vrrpd_query(%s)", vn);
2922 
2923         if ((vr = vrrpd_lookup_vr_by_name(vn)) == NULL) {
2924                 vrrp_log(VRRP_DBG1, "vrrpd_query(): %s does not exist", vn);
2925                 *sizep = sizeof (vrrp_ret_query_t);
2926                 ret->vrq_err = VRRP_ENOTFOUND;
2927                 return;
2928         }
2929 
2930         /*
2931          * Get the virtual IP list if the router is not in the INIT state.
2932          */
2933         if (vr->vvr_state != VRRP_STATE_INIT) {
2934                 vif = vr->vvr_vif;
2935                 TAILQ_FOREACH(ip, &vif->vvi_iplist, vip_next) {
2936                         vipcnt++;
2937                 }
2938         }
2939 
2940         *sizep = sizeof (vrrp_ret_query_t);
2941         *sizep += (vipcnt == 0) ? 0 : (vipcnt - 1) * sizeof (vrrp_addr_t);
2942         if (*sizep > size) {
2943                 vrrp_log(VRRP_ERR, "vrrpd_query(): not enough space to hold "
2944                     "%d virtual IPs", vipcnt);
2945                 *sizep = sizeof (vrrp_ret_query_t);
2946                 ret->vrq_err = VRRP_ETOOSMALL;
2947                 return;
2948         }
2949 
2950         (void) gettimeofday(&now, NULL);
2951 
2952         bzero(ret, *sizep);
2953         infop = &ret->vrq_qinfo;
2954         (void) memcpy(&infop->show_vi,
2955             &(vr->vvr_conf), sizeof (vrrp_vr_conf_t));
2956         (void) memcpy(&infop->show_vs,
2957             &(vr->vvr_sinfo), sizeof (vrrp_stateinfo_t));
2958         (void) strlcpy(infop->show_va.va_vnic, vr->vvr_vnic, MAXLINKNAMELEN);
2959         infop->show_vt.vt_since_last_tran = timeval_to_milli(
2960             timeval_delta(now, vr->vvr_sinfo.vs_st_time));
2961 
2962         if (vr->vvr_state == VRRP_STATE_INIT) {
2963                 ret->vrq_err = VRRP_SUCCESS;
2964                 return;
2965         }
2966 
2967         vipcnt = 0;
2968         TAILQ_FOREACH(ip, &vif->vvi_iplist, vip_next) {
2969                 (void) memcpy(&infop->show_va.va_vips[vipcnt++],
2970                     &ip->vip_addr, sizeof (vrrp_addr_t));
2971         }
2972         infop->show_va.va_vipcnt = vipcnt;
2973 
2974         (void) memcpy(&infop->show_va.va_primary,
2975             &vr->vvr_pif->vvi_pip->vip_addr, sizeof (vrrp_addr_t));
2976 
2977         (void) memcpy(&infop->show_vp, &(vr->vvr_peer), sizeof (vrrp_peer_t));
2978 
2979         /*
2980          * Check whether there is a peer.
2981          */
2982         if (!VRRPADDR_UNSPECIFIED(vr->vvr_conf.vvc_af,
2983             &(vr->vvr_peer.vp_addr))) {
2984                 infop->show_vt.vt_since_last_adv = timeval_to_milli(
2985                     timeval_delta(now, vr->vvr_peer.vp_time));
2986         }
2987 
2988         if (vr->vvr_state == VRRP_STATE_BACKUP) {
2989                 infop->show_vt.vt_master_down_intv =
2990                     MASTER_DOWN_INTERVAL_VR(vr);
2991         }
2992 
2993         ret->vrq_err = VRRP_SUCCESS;
2994 }
2995 
2996 /*
2997  * Build the VRRP packet (not including the IP header). Return the
2998  * payload length.
2999  *
3000  * If zero_pri is set to be B_TRUE, then this is the specical zero-priority
3001  * advertisement which is sent by the Master to indicate that it has been
3002  * stopped participating in VRRP.
3003  */
3004 static size_t
3005 vrrpd_build_vrrp(vrrp_vr_t *vr, uchar_t *buf, int buflen, boolean_t zero_pri)
3006 {
3007         /* LINTED E_BAD_PTR_CAST_ALIGN */
3008         vrrp_pkt_t      *vp = (vrrp_pkt_t *)buf;
3009         /* LINTED E_BAD_PTR_CAST_ALIGN */
3010         struct in_addr  *a4 = (struct in_addr *)(vp + 1);
3011         /* LINTED E_BAD_PTR_CAST_ALIGN */
3012         struct in6_addr *a6 = (struct in6_addr *)(vp + 1);
3013         vrrp_intf_t     *vif = vr->vvr_vif;
3014         vrrp_ip_t       *vip;
3015         int             af = vif->vvi_af;
3016         size_t          size = sizeof (vrrp_pkt_t);
3017         uint16_t        rsvd_adver_int;
3018         int             nip = 0;
3019 
3020         vrrp_log(VRRP_DBG1, "vrrpd_build_vrrp(%s, %s_priority): intv %d",
3021             vr->vvr_conf.vvc_name, zero_pri ? "zero" : "non-zero",
3022             vr->vvr_conf.vvc_adver_int);
3023 
3024         TAILQ_FOREACH(vip, &vif->vvi_iplist, vip_next) {
3025                 if ((size += ((af == AF_INET) ? sizeof (struct in_addr) :
3026                     sizeof (struct in6_addr))) > buflen) {
3027                         vrrp_log(VRRP_ERR, "vrrpd_build_vrrp(%s): buffer size "
3028                             "not big enough %d", vr->vvr_conf.vvc_name, size);
3029                         return (0);
3030                 }
3031 
3032                 if (af == AF_INET)
3033                         a4[nip++] = vip->vip_addr.in4.sin_addr;
3034                 else
3035                         a6[nip++] = vip->vip_addr.in6.sin6_addr;
3036         }
3037 
3038         if (nip == 0) {
3039                 vrrp_log(VRRP_ERR, "vrrpd_build_vrrp(%s): no virtual IP "
3040                     "address", vr->vvr_conf.vvc_name);
3041                 return (0);
3042         }
3043 
3044         vp->vp_vers_type = (VRRP_VERSION << 4) | VRRP_PKT_ADVERT;
3045         vp->vp_vrid = vr->vvr_conf.vvc_vrid;
3046         vp->vp_prio = zero_pri ? VRRP_PRIO_ZERO : vr->vvr_conf.vvc_pri;
3047 
3048         rsvd_adver_int = MSEC2CENTISEC(vr->vvr_conf.vvc_adver_int) & 0x0fff;
3049         vp->vp_rsvd_adver_int = htons(rsvd_adver_int);
3050         vp->vp_ipnum = nip;
3051 
3052         /*
3053          * Set the checksum to 0 first, then caculate it.
3054          */
3055         vp->vp_chksum = 0;
3056         if (af == AF_INET) {
3057                 vp->vp_chksum = vrrp_cksum4(
3058                     &vr->vvr_pif->vvi_pip->vip_addr.in4.sin_addr,
3059                     &vrrp_muladdr4.in4.sin_addr, size, vp);
3060         } else {
3061                 vp->vp_chksum = vrrp_cksum6(
3062                     &vr->vvr_pif->vvi_pip->vip_addr.in6.sin6_addr,
3063                     &vrrp_muladdr6.in6.sin6_addr, size, vp);
3064         }
3065 
3066         return (size);
3067 }
3068 
3069 /*
3070  * We need to build the IPv4 header on our own.
3071  */
3072 static vrrp_err_t
3073 vrrpd_send_adv_v4(vrrp_vr_t *vr, uchar_t *buf, size_t len, boolean_t zero_pri)
3074 {
3075         /* LINTED E_BAD_PTR_CAST_ALIGN */
3076         struct ip *ip = (struct ip *)buf;
3077         size_t plen;
3078 
3079         vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v4(%s)", vr->vvr_conf.vvc_name);
3080 
3081         if ((plen = vrrpd_build_vrrp(vr, buf + sizeof (struct ip),
3082             len - sizeof (struct ip), zero_pri)) == 0) {
3083                 return (VRRP_ETOOSMALL);
3084         }
3085 
3086         ip->ip_hl = sizeof (struct ip) >> 2;
3087         ip->ip_v = IPV4_VERSION;
3088         ip->ip_tos = 0;
3089         plen += sizeof (struct ip);
3090         ip->ip_len = htons(plen);
3091         ip->ip_off = 0;
3092         ip->ip_ttl = VRRP_IP_TTL;
3093         ip->ip_p = IPPROTO_VRRP;
3094         ip->ip_src = vr->vvr_pif->vvi_pip->vip_addr.in4.sin_addr;
3095         ip->ip_dst = vrrp_muladdr4.in4.sin_addr;
3096 
3097         /*
3098          * The kernel will set the IP cksum and the IPv4 identification.
3099          */
3100         ip->ip_id = 0;
3101         ip->ip_sum = 0;
3102 
3103         if ((len = sendto(vr->vvr_vif->vvi_sockfd, buf, plen, 0,
3104             (const struct sockaddr *)&vrrp_muladdr4,
3105             sizeof (struct sockaddr_in))) != plen) {
3106                 vrrp_log(VRRP_ERR, "vrrpd_send_adv_v4(): sendto() on "
3107                     "(vrid:%d, %s, %s) failed: %s sent:%d expect:%d",
3108                     vr->vvr_conf.vvc_vrid, vr->vvr_vif->vvi_ifname,
3109                     af_str(vr->vvr_conf.vvc_af), strerror(errno), len, plen);
3110                 return (VRRP_ESYS);
3111         }
3112 
3113         vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v4(%s) succeed",
3114             vr->vvr_conf.vvc_name);
3115         return (VRRP_SUCCESS);
3116 }
3117 
3118 static vrrp_err_t
3119 vrrpd_send_adv_v6(vrrp_vr_t *vr, uchar_t *buf, size_t len, boolean_t zero_pri)
3120 {
3121         struct msghdr msg6;
3122         size_t hoplimit_space = 0;
3123         size_t pktinfo_space = 0;
3124         size_t bufspace = 0;
3125         struct in6_pktinfo *pktinfop;
3126         struct cmsghdr *cmsgp;
3127         uchar_t *cmsg_datap;
3128         struct iovec iov;
3129         size_t plen;
3130 
3131         vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v6(%s)", vr->vvr_conf.vvc_name);
3132 
3133         if ((plen = vrrpd_build_vrrp(vr, buf, len, zero_pri)) == 0)
3134                 return (VRRP_ETOOSMALL);
3135 
3136         msg6.msg_control = NULL;
3137         msg6.msg_controllen = 0;
3138 
3139         hoplimit_space = sizeof (int);
3140         bufspace += sizeof (struct cmsghdr) + _MAX_ALIGNMENT +
3141             hoplimit_space + _MAX_ALIGNMENT;
3142 
3143         pktinfo_space = sizeof (struct in6_pktinfo);
3144         bufspace += sizeof (struct cmsghdr) + _MAX_ALIGNMENT +
3145             pktinfo_space + _MAX_ALIGNMENT;
3146 
3147         /*
3148          * We need to temporarily set the msg6.msg_controllen to bufspace
3149          * (we will later trim it to actual length used). This is needed because
3150          * CMSG_NXTHDR() uses it to check we have not exceeded the bounds.
3151          */
3152         bufspace += sizeof (struct cmsghdr);
3153         msg6.msg_controllen = bufspace;
3154 
3155         msg6.msg_control = (struct cmsghdr *)malloc(bufspace);
3156         if (msg6.msg_control == NULL) {
3157                 vrrp_log(VRRP_ERR, "vrrpd_send_adv_v6(%s): memory allocation "
3158                     "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
3159                 return (VRRP_ENOMEM);
3160         }
3161 
3162         cmsgp = CMSG_FIRSTHDR(&msg6);
3163 
3164         cmsgp->cmsg_level = IPPROTO_IPV6;
3165         cmsgp->cmsg_type = IPV6_HOPLIMIT;
3166         cmsg_datap = CMSG_DATA(cmsgp);
3167         /* LINTED */
3168         *(int *)cmsg_datap = VRRP_IP_TTL;
3169         cmsgp->cmsg_len = cmsg_datap + hoplimit_space - (uchar_t *)cmsgp;
3170         cmsgp = CMSG_NXTHDR(&msg6, cmsgp);
3171 
3172         cmsgp->cmsg_level = IPPROTO_IPV6;
3173         cmsgp->cmsg_type = IPV6_PKTINFO;
3174         cmsg_datap = CMSG_DATA(cmsgp);
3175 
3176         /* LINTED */
3177         pktinfop = (struct in6_pktinfo *)cmsg_datap;
3178         /*
3179          * We don't know if pktinfop->ipi6_addr is aligned properly,
3180          * therefore let's use bcopy, instead of assignment.
3181          */
3182         (void) bcopy(&vr->vvr_pif->vvi_pip->vip_addr.in6.sin6_addr,
3183             &pktinfop->ipi6_addr, sizeof (struct in6_addr));
3184 
3185         /*
3186          *  We can assume pktinfop->ipi6_ifindex is 32 bit aligned.
3187          */
3188         pktinfop->ipi6_ifindex = vr->vvr_vif->vvi_ifindex;
3189         cmsgp->cmsg_len = cmsg_datap + pktinfo_space - (uchar_t *)cmsgp;
3190         cmsgp = CMSG_NXTHDR(&msg6, cmsgp);
3191         msg6.msg_controllen = (char *)cmsgp - (char *)msg6.msg_control;
3192 
3193         msg6.msg_name = &vrrp_muladdr6;
3194         msg6.msg_namelen = sizeof (struct sockaddr_in6);
3195 
3196         iov.iov_base = buf;
3197         iov.iov_len = plen;
3198         msg6.msg_iov = &iov;
3199         msg6.msg_iovlen = 1;
3200 
3201         if ((len = sendmsg(vr->vvr_vif->vvi_sockfd,
3202             (const struct msghdr *)&msg6, 0)) != plen) {
3203                 vrrp_log(VRRP_ERR, "vrrpd_send_adv_v6(%s): sendmsg() failed: "
3204                     "%s expect %d sent %d", vr->vvr_conf.vvc_name,
3205                     strerror(errno), plen, len);
3206                 (void) free(msg6.msg_control);
3207                 return (VRRP_ESYS);
3208         }
3209 
3210         vrrp_log(VRRP_DBG1, "vrrpd_send_adv_v6(%s) succeed",
3211             vr->vvr_conf.vvc_name);
3212         (void) free(msg6.msg_control);
3213         return (VRRP_SUCCESS);
3214 }
3215 
3216 /*
3217  * Send the VRRP advertisement packets.
3218  */
3219 static vrrp_err_t
3220 vrrpd_send_adv(vrrp_vr_t *vr, boolean_t zero_pri)
3221 {
3222         uint64_t buf[(IP_MAXPACKET + 1)/8];
3223 
3224         vrrp_log(VRRP_DBG1, "vrrpd_send_adv(%s, %s_priority)",
3225             vr->vvr_conf.vvc_name, zero_pri ? "zero" : "non_zero");
3226 
3227         assert(vr->vvr_pif->vvi_pip != NULL);
3228 
3229         if (vr->vvr_pif->vvi_pip == NULL) {
3230                 vrrp_log(VRRP_DBG0, "vrrpd_send_adv(%s): no primary IP "
3231                     "address", vr->vvr_conf.vvc_name);
3232                 return (VRRP_EINVAL);
3233         }
3234 
3235         if (vr->vvr_conf.vvc_af == AF_INET) {
3236                 return (vrrpd_send_adv_v4(vr, (uchar_t *)buf,
3237                     sizeof (buf), zero_pri));
3238         } else {
3239                 return (vrrpd_send_adv_v6(vr, (uchar_t *)buf,
3240                     sizeof (buf), zero_pri));
3241         }
3242 }
3243 
3244 static void
3245 vrrpd_process_adv(vrrp_vr_t *vr, vrrp_addr_t *from, vrrp_pkt_t *vp)
3246 {
3247         vrrp_vr_conf_t *conf = &vr->vvr_conf;
3248         char            peer[INET6_ADDRSTRLEN];
3249         char            local[INET6_ADDRSTRLEN];
3250         int             addr_cmp;
3251         uint16_t        peer_adver_int;
3252 
3253         /* LINTED E_CONSTANT_CONDITION */
3254         VRRPADDR2STR(vr->vvr_conf.vvc_af, from, peer, INET6_ADDRSTRLEN,
3255             _B_FALSE);
3256         vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s) from %s", conf->vvc_name,
3257             peer);
3258 
3259         if (vr->vvr_state <= VRRP_STATE_INIT) {
3260                 vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): state: %s, not "
3261                     "ready", conf->vvc_name, vrrp_state2str(vr->vvr_state));
3262                 return;
3263         }
3264 
3265         peer_adver_int = CENTISEC2MSEC(ntohs(vp->vp_rsvd_adver_int) & 0x0fff);
3266 
3267         /* LINTED E_CONSTANT_CONDITION */
3268         VRRPADDR2STR(vr->vvr_pif->vvi_af, &vr->vvr_pif->vvi_pip->vip_addr,
3269             local, INET6_ADDRSTRLEN, _B_FALSE);
3270         vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): local/state/pri"
3271             "(%s/%s/%d) peer/pri/intv(%s/%d/%d)", conf->vvc_name, local,
3272             vrrp_state2str(vr->vvr_state), conf->vvc_pri, peer,
3273             vp->vp_prio, peer_adver_int);
3274 
3275         addr_cmp = ipaddr_cmp(vr->vvr_pif->vvi_af, from,
3276             &vr->vvr_pif->vvi_pip->vip_addr);
3277         if (addr_cmp == 0) {
3278                 vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): local message",
3279                     conf->vvc_name);
3280                 return;
3281         } else if (conf->vvc_pri == vp->vp_prio) {
3282                 vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): peer IP %s is %s"
3283                     " than the local IP %s", conf->vvc_name, peer,
3284                     addr_cmp > 0 ? "greater" : "less", local);
3285         }
3286 
3287         if (conf->vvc_pri == 255) {
3288                 vrrp_log(VRRP_ERR, "vrrpd_process_adv(%s): virtual address "
3289                     "owner received advertisement from %s", conf->vvc_name,
3290                     peer);
3291                 return;
3292         }
3293 
3294         (void) gettimeofday(&vr->vvr_peer_time, NULL);
3295         (void) memcpy(&vr->vvr_peer_addr, from, sizeof (vrrp_addr_t));
3296         vr->vvr_peer_prio = vp->vp_prio;
3297         vr->vvr_peer_adver_int = peer_adver_int;
3298 
3299         if (vr->vvr_state == VRRP_STATE_BACKUP) {
3300                 vr->vvr_master_adver_int = vr->vvr_peer_adver_int;
3301                 if ((vp->vp_prio == VRRP_PRIO_ZERO) ||
3302                     (conf->vvc_preempt == _B_FALSE ||
3303                     vp->vp_prio >= conf->vvc_pri)) {
3304                         (void) iu_cancel_timer(vrrpd_timerq,
3305                             vr->vvr_timer_id, NULL);
3306                         if (vp->vp_prio == VRRP_PRIO_ZERO) {
3307                                 /* the master stops participating in VRRP */
3308                                 vr->vvr_timeout = SKEW_TIME_VR(vr);
3309                         } else {
3310                                 vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
3311                         }
3312                         if ((vr->vvr_timer_id = iu_schedule_timer_ms(
3313                             vrrpd_timerq, vr->vvr_timeout, vrrp_b2m_timeout,
3314                             vr)) == -1) {
3315                                 vrrp_log(VRRP_ERR, "vrrpd_process_adv(%s): "
3316                                     "start vrrp_b2m_timeout(%d) failed",
3317                                     conf->vvc_name, vr->vvr_timeout);
3318                         } else {
3319                                 vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): "
3320                                     "start vrrp_b2m_timeout(%d)",
3321                                     conf->vvc_name, vr->vvr_timeout);
3322                         }
3323                 }
3324         } else if (vr->vvr_state == VRRP_STATE_MASTER) {
3325                 if (vp->vp_prio == VRRP_PRIO_ZERO) {
3326                         (void) vrrpd_send_adv(vr, _B_FALSE);
3327                         (void) iu_cancel_timer(vrrpd_timerq,
3328                             vr->vvr_timer_id, NULL);
3329                         if ((vr->vvr_timer_id = iu_schedule_timer_ms(
3330                             vrrpd_timerq, vr->vvr_timeout, vrrp_adv_timeout,
3331                             vr)) == -1) {
3332                                 vrrp_log(VRRP_ERR, "vrrpd_process_adv(%s): "
3333                                     "start vrrp_adv_timeout(%d) failed",
3334                                     conf->vvc_name, vr->vvr_timeout);
3335                         } else {
3336                                 vrrp_log(VRRP_DBG1, "vrrpd_process_adv(%s): "
3337                                     "start vrrp_adv_timeout(%d)",
3338                                     conf->vvc_name, vr->vvr_timeout);
3339                         }
3340                 } else if (vp->vp_prio > conf->vvc_pri ||
3341                     (vp->vp_prio == conf->vvc_pri && addr_cmp > 0)) {
3342                         (void) vrrpd_state_m2b(vr);
3343                 }
3344         } else {
3345                 assert(_B_FALSE);
3346         }
3347 }
3348 
3349 static vrrp_err_t
3350 vrrpd_process_vrrp(vrrp_intf_t *pif, vrrp_pkt_t *vp, size_t len,
3351     vrrp_addr_t *from)
3352 {
3353         vrrp_vr_t       *vr;
3354         uint8_t         vers_type;
3355         uint16_t        saved_cksum, cksum;
3356         char            peer[INET6_ADDRSTRLEN];
3357 
3358         /* LINTED E_CONSTANT_CONDITION */
3359         VRRPADDR2STR(pif->vvi_af, from, peer, INET6_ADDRSTRLEN, _B_FALSE);
3360         vrrp_log(VRRP_DBG0, "vrrpd_process_vrrp(%s) from %s", pif->vvi_ifname,
3361             peer);
3362 
3363         if (len < sizeof (vrrp_pkt_t)) {
3364                 vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s): invalid message "
3365                     "length %d", len);
3366                 return (VRRP_EINVAL);
3367         }
3368 
3369         /*
3370          * Verify: VRRP version number and packet type.
3371          */
3372         vers_type = ((vp->vp_vers_type & VRRP_VER_MASK) >> 4);
3373         if (vers_type != VRRP_VERSION) {
3374                 vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s) unsupported "
3375                     "version %d", pif->vvi_ifname, vers_type);
3376                 return (VRRP_EINVAL);
3377         }
3378 
3379         if (vp->vp_ipnum == 0) {
3380                 vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s): zero IPvX count",
3381                     pif->vvi_ifname);
3382                 return (VRRP_EINVAL);
3383         }
3384 
3385         if (len - sizeof (vrrp_pkt_t) !=
3386             vp->vp_ipnum * (pif->vvi_af == AF_INET ? sizeof (struct in_addr) :
3387             sizeof (struct in6_addr))) {
3388                 vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s): invalid IPvX count"
3389                     " %d", pif->vvi_ifname, vp->vp_ipnum);
3390                 return (VRRP_EINVAL);
3391         }
3392 
3393         vers_type = (vp->vp_vers_type & VRRP_TYPE_MASK);
3394 
3395         /*
3396          * verify: VRRP checksum. Note that vrrp_cksum returns network byte
3397          * order checksum value;
3398          */
3399         saved_cksum = vp->vp_chksum;
3400         vp->vp_chksum = 0;
3401         if (pif->vvi_af == AF_INET) {
3402                 cksum = vrrp_cksum4(&from->in4.sin_addr,
3403                     &vrrp_muladdr4.in4.sin_addr, len, vp);
3404         } else {
3405                 cksum = vrrp_cksum6(&from->in6.sin6_addr,
3406                     &vrrp_muladdr6.in6.sin6_addr, len, vp);
3407         }
3408 
3409         if (cksum != saved_cksum) {
3410                 vrrp_log(VRRP_ERR, "vrrpd_process_vrrp(%s) invalid "
3411                     "checksum: expected/real(0x%x/0x%x)", pif->vvi_ifname,
3412                     cksum, saved_cksum);
3413                 return (VRRP_EINVAL);
3414         }
3415 
3416         if ((vr = vrrpd_lookup_vr_by_vrid(pif->vvi_ifname, vp->vp_vrid,
3417             pif->vvi_af)) != NULL && vers_type == VRRP_PKT_ADVERT) {
3418                 vrrpd_process_adv(vr, from, vp);
3419         } else {
3420                 vrrp_log(VRRP_DBG1, "vrrpd_process_vrrp(%s) VRID(%d/%s) "
3421                     "not configured", pif->vvi_ifname, vp->vp_vrid,
3422                     af_str(pif->vvi_af));
3423         }
3424         return (VRRP_SUCCESS);
3425 }
3426 
3427 /*
3428  * IPv4 socket, the IPv4 header is included.
3429  */
3430 static vrrp_err_t
3431 vrrpd_process_adv_v4(vrrp_intf_t *pif, struct msghdr *msgp, size_t len)
3432 {
3433         char            abuf[INET6_ADDRSTRLEN];
3434         struct ip       *ip;
3435 
3436         vrrp_log(VRRP_DBG0, "vrrpd_process_adv_v4(%s, %d)",
3437             pif->vvi_ifname, len);
3438 
3439         ip = (struct ip *)msgp->msg_iov->iov_base;
3440 
3441         /* Sanity check */
3442         if (len < sizeof (struct ip) || len < ntohs(ip->ip_len)) {
3443                 vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid length "
3444                     "%d", pif->vvi_ifname, len);
3445                 return (VRRP_EINVAL);
3446         }
3447 
3448         assert(ip->ip_v == IPV4_VERSION);
3449         assert(ip->ip_p == IPPROTO_VRRP);
3450         assert(msgp->msg_namelen == sizeof (struct sockaddr_in));
3451 
3452         if (vrrp_muladdr4.in4.sin_addr.s_addr != ip->ip_dst.s_addr) {
3453                 vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
3454                     "destination %s", pif->vvi_ifname,
3455                     inet_ntop(pif->vvi_af, &(ip->ip_dst), abuf, sizeof (abuf)));
3456                 return (VRRP_EINVAL);
3457         }
3458 
3459         if (ip->ip_ttl != VRRP_IP_TTL) {
3460                 vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
3461                     "ttl %d", pif->vvi_ifname, ip->ip_ttl);
3462                 return (VRRP_EINVAL);
3463         }
3464 
3465         /*
3466          * Note that the ip_len contains only the IP payload length.
3467          */
3468         return (vrrpd_process_vrrp(pif,
3469             /* LINTED E_BAD_PTR_CAST_ALIGN */
3470             (vrrp_pkt_t *)((char *)ip + ip->ip_hl * 4), ntohs(ip->ip_len),
3471             (vrrp_addr_t *)msgp->msg_name));
3472 }
3473 
3474 /*
3475  * IPv6 socket, check the ancillary_data.
3476  */
3477 static vrrp_err_t
3478 vrrpd_process_adv_v6(vrrp_intf_t *pif, struct msghdr *msgp, size_t len)
3479 {
3480         struct cmsghdr          *cmsgp;
3481         uchar_t                 *cmsg_datap;
3482         struct in6_pktinfo      *pktinfop;
3483         char                    abuf[INET6_ADDRSTRLEN];
3484         int                     ttl;
3485 
3486         vrrp_log(VRRP_DBG1, "vrrpd_process_adv_v6(%s, %d)",
3487             pif->vvi_ifname, len);
3488 
3489         /* Sanity check */
3490         if (len < sizeof (vrrp_pkt_t)) {
3491                 vrrp_log(VRRP_ERR, "vrrpd_process_adv_v6(%s): invalid length "
3492                     "%d", pif->vvi_ifname, len);
3493                 return (VRRP_EINVAL);
3494         }
3495 
3496         assert(msgp->msg_namelen == sizeof (struct sockaddr_in6));
3497 
3498         for (cmsgp = CMSG_FIRSTHDR(msgp); cmsgp != NULL;
3499             cmsgp = CMSG_NXTHDR(msgp, cmsgp)) {
3500                 assert(cmsgp->cmsg_level == IPPROTO_IPV6);
3501                 cmsg_datap = CMSG_DATA(cmsgp);
3502 
3503                 switch (cmsgp->cmsg_type) {
3504                 case IPV6_HOPLIMIT:
3505                         /* LINTED E_BAD_PTR_CAST_ALIGN */
3506                         if ((ttl = *(int *)cmsg_datap) == VRRP_IP_TTL)
3507                                 break;
3508 
3509                         vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
3510                             "ttl %d", pif->vvi_ifname, ttl);
3511                         return (VRRP_EINVAL);
3512                 case IPV6_PKTINFO:
3513                         /* LINTED E_BAD_PTR_CAST_ALIGN */
3514                         pktinfop = (struct in6_pktinfo *)cmsg_datap;
3515                         if (IN6_ARE_ADDR_EQUAL(&pktinfop->ipi6_addr,
3516                             &vrrp_muladdr6.in6.sin6_addr)) {
3517                                 break;
3518                         }
3519 
3520                         vrrp_log(VRRP_ERR, "vrrpd_process_adv_v4(%s): invalid "
3521                             "destination %s", pif->vvi_ifname,
3522                             inet_ntop(pif->vvi_af, &pktinfop->ipi6_addr, abuf,
3523                             sizeof (abuf)));
3524                         return (VRRP_EINVAL);
3525                 }
3526         }
3527 
3528         return (vrrpd_process_vrrp(pif, msgp->msg_iov->iov_base, len,
3529             msgp->msg_name));
3530 }
3531 
3532 /* ARGSUSED */
3533 static void
3534 vrrpd_sock_handler(iu_eh_t *eh, int s, short events, iu_event_id_t id,
3535     void *arg)
3536 {
3537         struct msghdr           msg;
3538         vrrp_addr_t             from;
3539         uint64_t                buf[(IP_MAXPACKET + 1)/8];
3540         uint64_t                ancillary_data[(IP_MAXPACKET + 1)/8];
3541         vrrp_intf_t             *pif = arg;
3542         int                     af = pif->vvi_af;
3543         int                     len;
3544         struct iovec            iov;
3545 
3546         vrrp_log(VRRP_DBG1, "vrrpd_sock_handler(%s)", pif->vvi_ifname);
3547 
3548         msg.msg_name = (struct sockaddr *)&from;
3549         msg.msg_namelen = (af == AF_INET) ? sizeof (struct sockaddr_in) :
3550             sizeof (struct sockaddr_in6);
3551         iov.iov_base = (char *)buf;
3552         iov.iov_len = sizeof (buf);
3553         msg.msg_iov = &iov;
3554         msg.msg_iovlen = 1;
3555         msg.msg_control = ancillary_data;
3556         msg.msg_controllen = sizeof (ancillary_data);
3557 
3558         if ((len = recvmsg(s, &msg, 0)) == -1) {
3559                 vrrp_log(VRRP_ERR, "vrrpd_sock_handler() recvmsg(%s) "
3560                     "failed: %s", pif->vvi_ifname, strerror(errno));
3561                 return;
3562         }
3563 
3564         /*
3565          * Ignore packets whose control buffers that don't fit
3566          */
3567         if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
3568                 vrrp_log(VRRP_ERR, "vrrpd_sock_handler() %s buffer not "
3569                     "big enough", pif->vvi_ifname);
3570                 return;
3571         }
3572 
3573         if (af == AF_INET)
3574                 (void) vrrpd_process_adv_v4(pif, &msg, len);
3575         else
3576                 (void) vrrpd_process_adv_v6(pif, &msg, len);
3577 }
3578 
3579 /*
3580  * Create the socket which is used to receive VRRP packets. Virtual routers
3581  * that configured on the same physical interface share the same socket.
3582  */
3583 static vrrp_err_t
3584 vrrpd_init_rxsock(vrrp_vr_t *vr)
3585 {
3586         vrrp_intf_t *pif;       /* Physical interface used to recv packets */
3587         struct group_req greq;
3588         struct sockaddr_storage *muladdr;
3589         int af, proto;
3590         int on = 1;
3591         vrrp_err_t err = VRRP_SUCCESS;
3592 
3593         vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s)", vr->vvr_conf.vvc_name);
3594 
3595         /*
3596          * The RX sockets may already been initialized.
3597          */
3598         if ((pif = vr->vvr_pif) != NULL) {
3599                 vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s) already done on %s",
3600                     vr->vvr_conf.vvc_name, pif->vvi_ifname);
3601                 assert(pif->vvi_sockfd != -1);
3602                 return (VRRP_SUCCESS);
3603         }
3604 
3605         /*
3606          * If no IP addresses configured on the primary interface,
3607          * return failure.
3608          */
3609         af = vr->vvr_conf.vvc_af;
3610         pif = vrrpd_lookup_if(vr->vvr_conf.vvc_link, af);
3611         if (pif == NULL) {
3612                 vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s): no IP address "
3613                     "over %s/%s", vr->vvr_conf.vvc_name,
3614                     vr->vvr_conf.vvc_link, af_str(af));
3615                 return (VRRP_ENOPRIM);
3616         }
3617 
3618         proto = (af == AF_INET ? IPPROTO_IP : IPPROTO_IPV6);
3619         if (pif->vvi_nvr++ == 0) {
3620                 assert(pif->vvi_sockfd < 0);
3621                 pif->vvi_sockfd = socket(af, SOCK_RAW, IPPROTO_VRRP);
3622                 if (pif->vvi_sockfd < 0) {
3623                         vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): socket() "
3624                             "failed %s", vr->vvr_conf.vvc_name,
3625                             strerror(errno));
3626                         err = VRRP_ESYS;
3627                         goto done;
3628                 }
3629 
3630                 /*
3631                  * Join the multicast group to receive VRRP packets.
3632                  */
3633                 if (af == AF_INET) {
3634                         muladdr = (struct sockaddr_storage *)
3635                             (void *)&vrrp_muladdr4;
3636                 } else {
3637                         muladdr = (struct sockaddr_storage *)
3638                             (void *)&vrrp_muladdr6;
3639                 }
3640 
3641                 greq.gr_interface = pif->vvi_ifindex;
3642                 (void) memcpy(&greq.gr_group, muladdr,
3643                     sizeof (struct sockaddr_storage));
3644                 if (setsockopt(pif->vvi_sockfd, proto, MCAST_JOIN_GROUP, &greq,
3645                     sizeof (struct group_req)) < 0) {
3646                         vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
3647                             "join_group(%d) failed: %s", vr->vvr_conf.vvc_name,
3648                             pif->vvi_ifindex, strerror(errno));
3649                         err = VRRP_ESYS;
3650                         goto done;
3651                 } else {
3652                         vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s): "
3653                             "join_group(%d) succeeded", vr->vvr_conf.vvc_name,
3654                             pif->vvi_ifindex);
3655                 }
3656 
3657                 /*
3658                  * Unlike IPv4, the IPv6 raw socket does not pass the IP header
3659                  * when a packet is received. Call setsockopt() to receive such
3660                  * information.
3661                  */
3662                 if (af == AF_INET6) {
3663                         /*
3664                          * Enable receipt of destination address info
3665                          */
3666                         if (setsockopt(pif->vvi_sockfd, proto, IPV6_RECVPKTINFO,
3667                             (char *)&on, sizeof (on)) < 0) {
3668                                 vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
3669                                     "enable recvpktinfo failed: %s",
3670                                     vr->vvr_conf.vvc_name, strerror(errno));
3671                                 err = VRRP_ESYS;
3672                                 goto done;
3673                         }
3674 
3675                         /*
3676                          * Enable receipt of hoplimit info
3677                          */
3678                         if (setsockopt(pif->vvi_sockfd, proto,
3679                             IPV6_RECVHOPLIMIT, (char *)&on, sizeof (on)) < 0) {
3680                                 vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
3681                                     "enable recvhoplimit failed: %s",
3682                                     vr->vvr_conf.vvc_name, strerror(errno));
3683                                 err = VRRP_ESYS;
3684                                 goto done;
3685                         }
3686                 }
3687 
3688                 if ((pif->vvi_eid = iu_register_event(vrrpd_eh,
3689                     pif->vvi_sockfd, POLLIN, vrrpd_sock_handler, pif)) == -1) {
3690                         vrrp_log(VRRP_ERR, "vrrpd_init_rxsock(%s): "
3691                             "iu_register_event() failed",
3692                             vr->vvr_conf.vvc_name);
3693                         err = VRRP_ESYS;
3694                         goto done;
3695                 }
3696         } else {
3697                 vrrp_log(VRRP_DBG1, "vrrpd_init_rxsock(%s) over %s already "
3698                     "done %d", vr->vvr_conf.vvc_name, pif->vvi_ifname,
3699                     pif->vvi_nvr);
3700                 assert(IS_PRIMARY_INTF(pif));
3701         }
3702 
3703 done:
3704         vr->vvr_pif = pif;
3705         if (err != VRRP_SUCCESS)
3706                 vrrpd_fini_rxsock(vr);
3707 
3708         return (err);
3709 }
3710 
3711 /*
3712  * Delete the socket which is used to receive VRRP packets for the given
3713  * VRRP router. Since all virtual routers that configured on the same
3714  * physical interface share the same socket, the socket is only closed
3715  * when the last VRRP router share this socket is deleted.
3716  */
3717 static void
3718 vrrpd_fini_rxsock(vrrp_vr_t *vr)
3719 {
3720         vrrp_intf_t     *pif = vr->vvr_pif;
3721 
3722         vrrp_log(VRRP_DBG1, "vrrpd_fini_rxsock(%s)", vr->vvr_conf.vvc_name);
3723 
3724         if (pif == NULL)
3725                 return;
3726 
3727         if (--pif->vvi_nvr == 0) {
3728                 vrrp_log(VRRP_DBG1, "vrrpd_fini_rxsock(%s) over %s",
3729                     vr->vvr_conf.vvc_name, pif->vvi_ifname);
3730                 (void) iu_unregister_event(vrrpd_eh, pif->vvi_eid, NULL);
3731                 (void) close(pif->vvi_sockfd);
3732                 pif->vvi_pip = NULL;
3733                 pif->vvi_sockfd = -1;
3734                 pif->vvi_eid = -1;
3735         } else {
3736                 vrrp_log(VRRP_DBG1, "vrrpd_fini_rxsock(%s) over %s %d",
3737                     vr->vvr_conf.vvc_name, pif->vvi_ifname, pif->vvi_nvr);
3738         }
3739         vr->vvr_pif = NULL;
3740 }
3741 
3742 /*
3743  * Create the socket which is used to send VRRP packets. Further, set
3744  * the IFF_NOACCEPT flag based on the VRRP router's accept mode.
3745  */
3746 static vrrp_err_t
3747 vrrpd_init_txsock(vrrp_vr_t *vr)
3748 {
3749         int             af;
3750         vrrp_intf_t     *vif;
3751         vrrp_err_t      err;
3752 
3753         vrrp_log(VRRP_DBG1, "vrrpd_init_txsock(%s)", vr->vvr_conf.vvc_name);
3754 
3755         if (vr->vvr_vif != NULL) {
3756                 vrrp_log(VRRP_DBG1, "vrrpd_init_txsock(%s) already done on %s",
3757                     vr->vvr_conf.vvc_name, vr->vvr_vif->vvi_ifname);
3758                 return (VRRP_SUCCESS);
3759         }
3760 
3761         af = vr->vvr_conf.vvc_af;
3762         if ((vif = vrrpd_lookup_if(vr->vvr_vnic, af)) == NULL) {
3763                 vrrp_log(VRRP_DBG1, "vrrpd_init_txsock(%s) no IP address over "
3764                     "%s/%s", vr->vvr_conf.vvc_name, vr->vvr_vnic, af_str(af));
3765                 return (VRRP_ENOVIRT);
3766         }
3767 
3768         vr->vvr_vif = vif;
3769         if (vr->vvr_conf.vvc_af == AF_INET)
3770                 err = vrrpd_init_txsock_v4(vr);
3771         else
3772                 err = vrrpd_init_txsock_v6(vr);
3773 
3774         if (err != VRRP_SUCCESS)
3775                 goto done;
3776 
3777         /*
3778          * The interface should start with IFF_NOACCEPT flag not set, only
3779          * call this function when the VRRP router requires IFF_NOACCEPT.
3780          */
3781         if (!vr->vvr_conf.vvc_accept)
3782                 err = vrrpd_set_noaccept(vr, _B_TRUE);
3783 
3784 done:
3785         if (err != VRRP_SUCCESS) {
3786                 (void) close(vif->vvi_sockfd);
3787                 vif->vvi_sockfd = -1;
3788                 vr->vvr_vif = NULL;
3789         }
3790 
3791         return (err);
3792 }
3793 
3794 /*
3795  * Create the IPv4 socket which is used to send VRRP packets. Note that
3796  * the destination MAC address of VRRP advertisement must be the virtual
3797  * MAC address, so we specify the output interface to be the specific VNIC.
3798  */
3799 static vrrp_err_t
3800 vrrpd_init_txsock_v4(vrrp_vr_t *vr)
3801 {
3802         vrrp_intf_t *vif;       /* VNIC interface used to send packets */
3803         vrrp_ip_t *vip;         /* The first IP over the VNIC */
3804         int on = 1;
3805         char off = 0;
3806         vrrp_err_t err = VRRP_SUCCESS;
3807         char abuf[INET6_ADDRSTRLEN];
3808 
3809         vif = vr->vvr_vif;
3810         assert(vr->vvr_conf.vvc_af == AF_INET);
3811         assert(vif != NULL);
3812 
3813         vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v4(%s) over %s",
3814             vr->vvr_conf.vvc_name, vif->vvi_ifname);
3815 
3816         if (vif->vvi_sockfd != -1) {
3817                 vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v4(%s) already done "
3818                     "over %s", vr->vvr_conf.vvc_name, vif->vvi_ifname);
3819                 return (VRRP_SUCCESS);
3820         }
3821 
3822         vif->vvi_sockfd = socket(vif->vvi_af, SOCK_RAW, IPPROTO_VRRP);
3823         if (vif->vvi_sockfd < 0) {
3824                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): socket() "
3825                     "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
3826                 err = VRRP_ESYS;
3827                 goto done;
3828         }
3829 
3830         /*
3831          * Include the IP header, so that we can specify the IP address/ttl.
3832          */
3833         if (setsockopt(vif->vvi_sockfd, IPPROTO_IP, IP_HDRINCL, (char *)&on,
3834             sizeof (on)) < 0) {
3835                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): ip_hdrincl "
3836                     "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
3837                 err = VRRP_ESYS;
3838                 goto done;
3839         }
3840 
3841         /*
3842          * Disable multicast loopback.
3843          */
3844         if (setsockopt(vif->vvi_sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &off,
3845             sizeof (char)) == -1) {
3846                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): disable "
3847                     "multicast_loop failed: %s", vr->vvr_conf.vvc_name,
3848                     strerror(errno));
3849                 err = VRRP_ESYS;
3850                 goto done;
3851         }
3852 
3853         vip = TAILQ_FIRST(&vif->vvi_iplist);
3854         /* LINTED E_CONSTANT_CONDITION */
3855         VRRPADDR2STR(vif->vvi_af, &vip->vip_addr, abuf, INET6_ADDRSTRLEN,
3856             _B_FALSE);
3857 
3858         /*
3859          * Set the output interface to send the VRRP packet.
3860          */
3861         if (setsockopt(vif->vvi_sockfd, IPPROTO_IP, IP_MULTICAST_IF,
3862             &vip->vip_addr.in4.sin_addr, sizeof (struct in_addr)) < 0) {
3863                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v4(%s): multcast_if(%s) "
3864                     "failed: %s", vr->vvr_conf.vvc_name, abuf, strerror(errno));
3865                 err = VRRP_ESYS;
3866         } else {
3867                 vrrp_log(VRRP_DBG0, "vrrpd_init_txsock_v4(%s): multcast_if(%s) "
3868                     "succeed", vr->vvr_conf.vvc_name, abuf);
3869         }
3870 
3871 done:
3872         if (err != VRRP_SUCCESS) {
3873                 (void) close(vif->vvi_sockfd);
3874                 vif->vvi_sockfd = -1;
3875         }
3876 
3877         return (err);
3878 }
3879 
3880 /*
3881  * Create the IPv6 socket which is used to send VRRP packets. Note that
3882  * the destination must be the virtual MAC address, so we specify the output
3883  * interface to be the specific VNIC.
3884  */
3885 static vrrp_err_t
3886 vrrpd_init_txsock_v6(vrrp_vr_t *vr)
3887 {
3888         vrrp_intf_t *vif;       /* VNIC interface used to send packets */
3889         int off = 0, ttl = VRRP_IP_TTL;
3890         vrrp_err_t err = VRRP_SUCCESS;
3891 
3892         vif = vr->vvr_vif;
3893         assert(vr->vvr_conf.vvc_af == AF_INET6);
3894         assert(vif != NULL);
3895 
3896         vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v6(%s) over %s",
3897             vr->vvr_conf.vvc_name, vif->vvi_ifname);
3898 
3899         if (vif->vvi_sockfd != -1) {
3900                 vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v6(%s) already done "
3901                     "over %s", vr->vvr_conf.vvc_name, vif->vvi_ifname);
3902                 return (VRRP_SUCCESS);
3903         }
3904 
3905         vif->vvi_sockfd = socket(vif->vvi_af, SOCK_RAW, IPPROTO_VRRP);
3906         if (vif->vvi_sockfd < 0) {
3907                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): socket() "
3908                     "failed: %s", vr->vvr_conf.vvc_name, strerror(errno));
3909                 err = VRRP_ESYS;
3910                 goto done;
3911         }
3912 
3913         /*
3914          * Disable multicast loopback.
3915          */
3916         if (setsockopt(vif->vvi_sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
3917             &off, sizeof (int)) == -1) {
3918                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): disable "
3919                     "multicast_loop failed: %s", vr->vvr_conf.vvc_name,
3920                     strerror(errno));
3921                 err = VRRP_ESYS;
3922                 goto done;
3923         }
3924 
3925         /*
3926          * Set the multicast TTL.
3927          */
3928         if (setsockopt(vif->vvi_sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
3929             &ttl, sizeof (int)) == -1) {
3930                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): enable "
3931                     "multicast_hops %d failed: %s", vr->vvr_conf.vvc_name,
3932                     ttl, strerror(errno));
3933                 err = VRRP_ESYS;
3934                 goto done;
3935         }
3936 
3937         /*
3938          * Set the output interface to send the VRRP packet.
3939          */
3940         if (setsockopt(vif->vvi_sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
3941             &vif->vvi_ifindex, sizeof (uint32_t)) < 0) {
3942                 vrrp_log(VRRP_ERR, "vrrpd_init_txsock_v6(%s): multicast_if(%d) "
3943                     "failed: %s", vr->vvr_conf.vvc_name, vif->vvi_ifindex,
3944                     strerror(errno));
3945                 err = VRRP_ESYS;
3946         } else {
3947                 vrrp_log(VRRP_DBG1, "vrrpd_init_txsock_v6(%s): multicast_if(%d)"
3948                     " succeed", vr->vvr_conf.vvc_name, vif->vvi_ifindex);
3949         }
3950 
3951 done:
3952         if (err != VRRP_SUCCESS) {
3953                 (void) close(vif->vvi_sockfd);
3954                 vif->vvi_sockfd = -1;
3955         }
3956 
3957         return (err);
3958 }
3959 
3960 /*
3961  * Delete the socket which is used to send VRRP packets. Further, clear
3962  * the IFF_NOACCEPT flag based on the VRRP router's accept mode.
3963  */
3964 static void
3965 vrrpd_fini_txsock(vrrp_vr_t *vr)
3966 {
3967         vrrp_intf_t *vif = vr->vvr_vif;
3968 
3969         vrrp_log(VRRP_DBG1, "vrrpd_fini_txsock(%s)", vr->vvr_conf.vvc_name);
3970 
3971         if (vif != NULL) {
3972                 if (!vr->vvr_conf.vvc_accept)
3973                         (void) vrrpd_set_noaccept(vr, _B_FALSE);
3974                 (void) close(vif->vvi_sockfd);
3975                 vif->vvi_sockfd = -1;
3976                 vr->vvr_vif = NULL;
3977         }
3978 }
3979 
3980 /*
3981  * Given the the pseudo header cksum value (sum), caculate the cksum with
3982  * the rest of VRRP packet.
3983  */
3984 static uint16_t
3985 in_cksum(int sum, uint16_t plen, void *p)
3986 {
3987         int nleft;
3988         uint16_t *w;
3989         uint16_t answer;
3990         uint16_t odd_byte = 0;
3991 
3992         nleft = plen;
3993         w = (uint16_t *)p;
3994         while (nleft > 1) {
3995                 sum += *w++;
3996                 nleft -= 2;
3997         }
3998 
3999         /* mop up an odd byte, if necessary */
4000         if (nleft == 1) {
4001                 *(uchar_t *)(&odd_byte) = *(uchar_t *)w;
4002                 sum += odd_byte;
4003         }
4004 
4005         /*
4006          * add back carry outs from top 16 bits to low 16 bits
4007          */
4008         sum = (sum >> 16) + (sum & 0xffff);   /* add hi 16 to low 16 */
4009         sum += (sum >> 16);                       /* add carry */
4010         answer = ~sum;                          /* truncate to 16 bits */
4011         return (answer == 0 ? ~0 : answer);
4012 }
4013 
4014 /* Pseudo header for v4 */
4015 struct pshv4 {
4016         struct in_addr  ph4_src;
4017         struct in_addr  ph4_dst;
4018         uint8_t         ph4_zero;       /* always zero */
4019         uint8_t         ph4_protocol;   /* protocol used, IPPROTO_VRRP */
4020         uint16_t        ph4_len;        /* VRRP payload len */
4021 };
4022 
4023 /*
4024  * Checksum routine for VRRP checksum. Note that plen is the upper-layer
4025  * packet length (in the host byte order), and both IP source and destination
4026  * addresses are in the network byte order.
4027  */
4028 static uint16_t
4029 vrrp_cksum4(struct in_addr *src, struct in_addr *dst, uint16_t plen,
4030     vrrp_pkt_t *vp)
4031 {
4032         struct pshv4 ph4;
4033         int nleft;
4034         uint16_t *w;
4035         int sum = 0;
4036 
4037         ph4.ph4_src = *src;
4038         ph4.ph4_dst = *dst;
4039         ph4.ph4_zero = 0;
4040         ph4.ph4_protocol = IPPROTO_VRRP;
4041         ph4.ph4_len = htons(plen);
4042 
4043         /*
4044          *  Our algorithm is simple, using a 32 bit accumulator (sum),
4045          *  we add sequential 16 bit words to it, and at the end, fold
4046          *  back all the carry bits from the top 16 bits into the lower
4047          *  16 bits.
4048          */
4049         nleft = sizeof (struct pshv4);
4050         w = (uint16_t *)&ph4;
4051         while (nleft > 0) {
4052                 sum += *w++;
4053                 nleft -= 2;
4054         }
4055 
4056         return (in_cksum(sum, plen, vp));
4057 }
4058 
4059 /* Pseudo header for v6 */
4060 struct pshv6 {
4061         struct in6_addr ph6_src;
4062         struct in6_addr ph6_dst;
4063         uint32_t        ph6_len;        /* VRRP payload len */
4064         uint32_t        ph6_zero : 24,
4065                         ph6_protocol : 8; /* protocol used, IPPROTO_VRRP */
4066 };
4067 
4068 /*
4069  * Checksum routine for VRRP checksum. Note that plen is the upper-layer
4070  * packet length (in the host byte order), and both IP source and destination
4071  * addresses are in the network byte order.
4072  */
4073 static uint16_t
4074 vrrp_cksum6(struct in6_addr *src, struct in6_addr *dst, uint16_t plen,
4075     vrrp_pkt_t *vp)
4076 {
4077         struct pshv6 ph6;
4078         int nleft;
4079         uint16_t *w;
4080         int sum = 0;
4081 
4082         ph6.ph6_src = *src;
4083         ph6.ph6_dst = *dst;
4084         ph6.ph6_zero = 0;
4085         ph6.ph6_protocol = IPPROTO_VRRP;
4086         ph6.ph6_len = htonl((uint32_t)plen);
4087 
4088         /*
4089          *  Our algorithm is simple, using a 32 bit accumulator (sum),
4090          *  we add sequential 16 bit words to it, and at the end, fold
4091          *  back all the carry bits from the top 16 bits into the lower
4092          *  16 bits.
4093          */
4094         nleft = sizeof (struct pshv6);
4095         w = (uint16_t *)&ph6;
4096         while (nleft > 0) {
4097                 sum += *w++;
4098                 nleft -= 2;
4099         }
4100 
4101         return (in_cksum(sum, plen, vp));
4102 }
4103 
4104 vrrp_err_t
4105 vrrpd_state_i2m(vrrp_vr_t *vr)
4106 {
4107         vrrp_err_t      err;
4108 
4109         vrrp_log(VRRP_DBG1, "vrrpd_state_i2m(%s)", vr->vvr_conf.vvc_name);
4110 
4111         vrrpd_state_trans(VRRP_STATE_INIT, VRRP_STATE_MASTER, vr);
4112         if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
4113                 return (err);
4114 
4115         (void) vrrpd_send_adv(vr, _B_FALSE);
4116 
4117         vr->vvr_err = VRRP_SUCCESS;
4118         vr->vvr_timeout = vr->vvr_conf.vvc_adver_int;
4119         if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
4120             vr->vvr_timeout, vrrp_adv_timeout, vr)) == -1) {
4121                 vrrp_log(VRRP_ERR, "vrrpd_state_i2m(): unable to start timer");
4122                 return (VRRP_ESYS);
4123         } else {
4124                 vrrp_log(VRRP_DBG1, "vrrpd_state_i2m(%s): start "
4125                     "vrrp_adv_timeout(%d)", vr->vvr_conf.vvc_name,
4126                     vr->vvr_timeout);
4127         }
4128         return (VRRP_SUCCESS);
4129 }
4130 
4131 vrrp_err_t
4132 vrrpd_state_i2b(vrrp_vr_t *vr)
4133 {
4134         vrrp_err_t      err;
4135 
4136         vrrp_log(VRRP_DBG1, "vrrpd_state_i2b(%s)", vr->vvr_conf.vvc_name);
4137 
4138         vrrpd_state_trans(VRRP_STATE_INIT, VRRP_STATE_BACKUP, vr);
4139         if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
4140                 return (err);
4141 
4142         /*
4143          * Reinitialize the Master advertisement interval to be the configured
4144          * value.
4145          */
4146         vr->vvr_err = VRRP_SUCCESS;
4147         vr->vvr_master_adver_int = vr->vvr_conf.vvc_adver_int;
4148         vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
4149         if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
4150             vr->vvr_timeout, vrrp_b2m_timeout, vr)) == -1) {
4151                 vrrp_log(VRRP_ERR, "vrrpd_state_i2b(): unable to set timer");
4152                 return (VRRP_ESYS);
4153         } else {
4154                 vrrp_log(VRRP_DBG1, "vrrpd_state_i2b(%s): start "
4155                     "vrrp_b2m_timeout(%d)", vr->vvr_conf.vvc_name,
4156                     vr->vvr_timeout);
4157         }
4158         return (VRRP_SUCCESS);
4159 }
4160 
4161 void
4162 vrrpd_state_m2i(vrrp_vr_t *vr)
4163 {
4164         vrrp_log(VRRP_DBG1, "vrrpd_state_m2i(%s)", vr->vvr_conf.vvc_name);
4165 
4166         vrrpd_state_trans(VRRP_STATE_MASTER, VRRP_STATE_INIT, vr);
4167         (void) vrrpd_virtualip_update(vr, _B_TRUE);
4168         bzero(&vr->vvr_peer, sizeof (vrrp_peer_t));
4169         (void) iu_cancel_timer(vrrpd_timerq, vr->vvr_timer_id, NULL);
4170 }
4171 
4172 void
4173 vrrpd_state_b2i(vrrp_vr_t *vr)
4174 {
4175         vrrp_log(VRRP_DBG1, "vrrpd_state_b2i(%s)", vr->vvr_conf.vvc_name);
4176 
4177         bzero(&vr->vvr_peer, sizeof (vrrp_peer_t));
4178         (void) iu_cancel_timer(vrrpd_timerq, vr->vvr_timer_id, NULL);
4179         vrrpd_state_trans(VRRP_STATE_BACKUP, VRRP_STATE_INIT, vr);
4180         (void) vrrpd_virtualip_update(vr, _B_TRUE);
4181 }
4182 
4183 /* ARGSUSED */
4184 static void
4185 vrrp_b2m_timeout(iu_tq_t *tq, void *arg)
4186 {
4187         vrrp_vr_t *vr = (vrrp_vr_t *)arg;
4188 
4189         vrrp_log(VRRP_DBG1, "vrrp_b2m_timeout(%s)", vr->vvr_conf.vvc_name);
4190         (void) vrrpd_state_b2m(vr);
4191 }
4192 
4193 /* ARGSUSED */
4194 static void
4195 vrrp_adv_timeout(iu_tq_t *tq, void *arg)
4196 {
4197         vrrp_vr_t *vr = (vrrp_vr_t *)arg;
4198 
4199         vrrp_log(VRRP_DBG1, "vrrp_adv_timeout(%s)", vr->vvr_conf.vvc_name);
4200 
4201         (void) vrrpd_send_adv(vr, _B_FALSE);
4202         if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
4203             vr->vvr_timeout, vrrp_adv_timeout, vr)) == -1) {
4204                 vrrp_log(VRRP_ERR, "vrrp_adv_timeout(%s): start timer failed",
4205                     vr->vvr_conf.vvc_name);
4206         } else {
4207                 vrrp_log(VRRP_DBG1, "vrrp_adv_timeout(%s): start "
4208                     "vrrp_adv_timeout(%d)", vr->vvr_conf.vvc_name,
4209                     vr->vvr_timeout);
4210         }
4211 }
4212 
4213 vrrp_err_t
4214 vrrpd_state_b2m(vrrp_vr_t *vr)
4215 {
4216         vrrp_err_t      err;
4217 
4218         vrrp_log(VRRP_DBG1, "vrrpd_state_b2m(%s)", vr->vvr_conf.vvc_name);
4219 
4220         vrrpd_state_trans(VRRP_STATE_BACKUP, VRRP_STATE_MASTER, vr);
4221         if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
4222                 return (err);
4223         (void) vrrpd_send_adv(vr, _B_FALSE);
4224 
4225         vr->vvr_timeout = vr->vvr_conf.vvc_adver_int;
4226         if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
4227             vr->vvr_timeout, vrrp_adv_timeout, vr)) == -1) {
4228                 vrrp_log(VRRP_ERR, "vrrpd_state_b2m(%s): start timer failed",
4229                     vr->vvr_conf.vvc_name);
4230                 return (VRRP_ESYS);
4231         } else {
4232                 vrrp_log(VRRP_DBG1, "vrrpd_state_b2m(%s): start "
4233                     "vrrp_adv_timeout(%d)", vr->vvr_conf.vvc_name,
4234                     vr->vvr_timeout);
4235         }
4236         return (VRRP_SUCCESS);
4237 }
4238 
4239 vrrp_err_t
4240 vrrpd_state_m2b(vrrp_vr_t *vr)
4241 {
4242         vrrp_err_t      err;
4243 
4244         vrrp_log(VRRP_DBG1, "vrrpd_state_m2b(%s)", vr->vvr_conf.vvc_name);
4245 
4246         vrrpd_state_trans(VRRP_STATE_MASTER, VRRP_STATE_BACKUP, vr);
4247         if ((err = vrrpd_virtualip_update(vr, _B_FALSE)) != VRRP_SUCCESS)
4248                 return (err);
4249 
4250         /*
4251          * Cancel the adver_timer.
4252          */
4253         vr->vvr_master_adver_int = vr->vvr_peer_adver_int;
4254         (void) iu_cancel_timer(vrrpd_timerq, vr->vvr_timer_id, NULL);
4255         vr->vvr_timeout = MASTER_DOWN_INTERVAL_VR(vr);
4256         if ((vr->vvr_timer_id = iu_schedule_timer_ms(vrrpd_timerq,
4257             vr->vvr_timeout, vrrp_b2m_timeout, vr)) == -1) {
4258                 vrrp_log(VRRP_ERR, "vrrpd_state_m2b(%s): start timer failed",
4259                     vr->vvr_conf.vvc_name);
4260         } else {
4261                 vrrp_log(VRRP_DBG1, "vrrpd_state_m2b(%s) start "
4262                     "vrrp_b2m_timeout(%d)", vr->vvr_conf.vvc_name,
4263                     vr->vvr_timeout);
4264         }
4265         return (VRRP_SUCCESS);
4266 }
4267 
4268 /*
4269  * Set the IFF_NOACCESS flag on the VNIC interface of the VRRP router
4270  * based on its access mode.
4271  */
4272 static vrrp_err_t
4273 vrrpd_set_noaccept(vrrp_vr_t *vr, boolean_t on)
4274 {
4275         vrrp_intf_t *vif = vr->vvr_vif;
4276         uint64_t curr_flags;
4277         struct lifreq lifr;
4278         int s;
4279 
4280         vrrp_log(VRRP_DBG1, "vrrpd_set_noaccept(%s, %s)",
4281             vr->vvr_conf.vvc_name, on ? "on" : "off");
4282 
4283         /*
4284          * Possibly no virtual address exists on this VRRP router yet.
4285          */
4286         if (vif == NULL)
4287                 return (VRRP_SUCCESS);
4288 
4289         vrrp_log(VRRP_DBG1, "vrrpd_set_noaccept(%s, %s)",
4290             vif->vvi_ifname, vrrp_state2str(vr->vvr_state));
4291 
4292         s = (vif->vvi_af == AF_INET) ? vrrpd_ctlsock_fd : vrrpd_ctlsock6_fd;
4293         (void) strncpy(lifr.lifr_name, vif->vvi_ifname,
4294             sizeof (lifr.lifr_name));
4295         if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
4296                 if (errno != ENXIO && errno != ENOENT) {
4297                         vrrp_log(VRRP_ERR, "vrrpd_set_noaccept(): "
4298                             "SIOCGLIFFLAGS on %s failed: %s",
4299                             vif->vvi_ifname, strerror(errno));
4300                 }
4301                 return (VRRP_ESYS);
4302         }
4303 
4304         curr_flags = lifr.lifr_flags;
4305         if (on)
4306                 lifr.lifr_flags |= IFF_NOACCEPT;
4307         else
4308                 lifr.lifr_flags &= ~IFF_NOACCEPT;
4309 
4310         if (lifr.lifr_flags != curr_flags) {
4311                 if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
4312                         if (errno != ENXIO && errno != ENOENT) {
4313                                 vrrp_log(VRRP_ERR, "vrrpd_set_noaccept(%s): "
4314                                     "SIOCSLIFFLAGS 0x%llx on %s failed: %s",
4315                                     on ? "no_accept" : "accept",
4316                                     lifr.lifr_flags, vif->vvi_ifname,
4317                                     strerror(errno));
4318                         }
4319                         return (VRRP_ESYS);
4320                 }
4321         }
4322         return (VRRP_SUCCESS);
4323 }
4324 
4325 static vrrp_err_t
4326 vrrpd_virtualip_updateone(vrrp_intf_t *vif, vrrp_ip_t *ip, boolean_t checkonly)
4327 {
4328         vrrp_state_t    state = vif->vvi_vr_state;
4329         struct lifreq   lifr;
4330         char            abuf[INET6_ADDRSTRLEN];
4331         int             af = vif->vvi_af;
4332         uint64_t        curr_flags;
4333         int             s;
4334 
4335         assert(IS_VIRTUAL_INTF(vif));
4336 
4337         /* LINTED E_CONSTANT_CONDITION */
4338         VRRPADDR2STR(af, &ip->vip_addr, abuf, INET6_ADDRSTRLEN, _B_FALSE);
4339         vrrp_log(VRRP_DBG1, "vrrpd_virtualip_updateone(%s, %s%s)",
4340             vif->vvi_ifname, abuf, checkonly ? ", checkonly" : "");
4341 
4342         s = (af == AF_INET) ? vrrpd_ctlsock_fd : vrrpd_ctlsock6_fd;
4343         (void) strncpy(lifr.lifr_name, ip->vip_lifname,
4344             sizeof (lifr.lifr_name));
4345         if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
4346                 if (errno != ENXIO && errno != ENOENT) {
4347                         vrrp_log(VRRP_ERR, "vrrpd_virtualip_updateone(%s): "
4348                             "SIOCGLIFFLAGS on %s/%s failed: %s",
4349                             vif->vvi_ifname, lifr.lifr_name, abuf,
4350                             strerror(errno));
4351                 }
4352                 return (VRRP_ESYS);
4353         }
4354 
4355         curr_flags = lifr.lifr_flags;
4356         if (state == VRRP_STATE_MASTER)
4357                 lifr.lifr_flags |= IFF_UP;
4358         else
4359                 lifr.lifr_flags &= ~IFF_UP;
4360 
4361         if (lifr.lifr_flags == curr_flags)
4362                 return (VRRP_SUCCESS);
4363 
4364         if (checkonly) {
4365                 vrrp_log(VRRP_ERR, "VRRP virtual IP %s/%s was brought %s",
4366                     ip->vip_lifname, abuf,
4367                     state == VRRP_STATE_MASTER ? "down" : "up");
4368                 return (VRRP_ESYS);
4369         } else if (ioctl(s, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) {
4370                 if (errno != ENXIO && errno != ENOENT) {
4371                         vrrp_log(VRRP_ERR, "vrrpd_virtualip_updateone(%s, %s): "
4372                             "bring %s %s/%s failed: %s",
4373                             vif->vvi_ifname, vrrp_state2str(state),
4374                             state == VRRP_STATE_MASTER ? "up" : "down",
4375                             ip->vip_lifname, abuf, strerror(errno));
4376                 }
4377                 return (VRRP_ESYS);
4378         }
4379         return (VRRP_SUCCESS);
4380 }
4381 
4382 static vrrp_err_t
4383 vrrpd_virtualip_update(vrrp_vr_t *vr, boolean_t checkonly)
4384 {
4385         vrrp_state_t            state;
4386         vrrp_intf_t             *vif = vr->vvr_vif;
4387         vrrp_ip_t               *ip, *nextip;
4388         char                    abuf[INET6_ADDRSTRLEN];
4389         vrrp_err_t              err;
4390 
4391         vrrp_log(VRRP_DBG1, "vrrpd_virtualip_update(%s, %s, %s)%s",
4392             vr->vvr_conf.vvc_name, vrrp_state2str(vr->vvr_state),
4393             vif->vvi_ifname, checkonly ? " checkonly" : "");
4394 
4395         state = vr->vvr_state;
4396         assert(vif != NULL);
4397         assert(IS_VIRTUAL_INTF(vif));
4398         assert(vif->vvi_vr_state != state);
4399         vif->vvi_vr_state = state;
4400         for (ip = TAILQ_FIRST(&vif->vvi_iplist); ip != NULL; ip = nextip) {
4401                 nextip = TAILQ_NEXT(ip, vip_next);
4402                 err = vrrpd_virtualip_updateone(vif, ip, _B_FALSE);
4403                 if (!checkonly && err != VRRP_SUCCESS) {
4404                         /* LINTED E_CONSTANT_CONDITION */
4405                         VRRPADDR2STR(vif->vvi_af, &ip->vip_addr, abuf,
4406                             INET6_ADDRSTRLEN, _B_FALSE);
4407                         vrrp_log(VRRP_DBG1, "vrrpd_virtualip_update() update "
4408                             "%s over %s failed", abuf, vif->vvi_ifname);
4409                         vrrpd_delete_ip(vif, ip);
4410                 }
4411         }
4412 
4413         /*
4414          * The IP address is deleted when it is failed to be brought
4415          * up. If no IP addresses are left, delete this interface.
4416          */
4417         if (!checkonly && TAILQ_EMPTY(&vif->vvi_iplist)) {
4418                 vrrp_log(VRRP_DBG0, "vrrpd_virtualip_update(): "
4419                     "no IP left over %s", vif->vvi_ifname);
4420                 vrrpd_delete_if(vif, _B_TRUE);
4421                 return (VRRP_ENOVIRT);
4422         }
4423         return (VRRP_SUCCESS);
4424 }
4425 
4426 void
4427 vrrpd_state_trans(vrrp_state_t prev_s, vrrp_state_t s, vrrp_vr_t *vr)
4428 {
4429         vrrp_log(VRRP_DBG1, "vrrpd_state_trans(%s): %s --> %s",
4430             vr->vvr_conf.vvc_name, vrrp_state2str(prev_s), vrrp_state2str(s));
4431 
4432         assert(vr->vvr_state == prev_s);
4433         vr->vvr_state = s;
4434         vr->vvr_prev_state = prev_s;
4435         (void) gettimeofday(&vr->vvr_st_time, NULL);
4436         (void) vrrpd_post_event(vr->vvr_conf.vvc_name, prev_s, s);
4437 }
4438 
4439 static int
4440 vrrpd_post_event(const char *name, vrrp_state_t prev_st, vrrp_state_t st)
4441 {
4442         sysevent_id_t   eid;
4443         nvlist_t        *nvl = NULL;
4444 
4445         /*
4446          * sysevent is not supported in the non-global zone
4447          */
4448         if (getzoneid() != GLOBAL_ZONEID)
4449                 return (0);
4450 
4451         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
4452                 goto failed;
4453 
4454         if (nvlist_add_uint8(nvl, VRRP_EVENT_VERSION,
4455             VRRP_EVENT_CUR_VERSION) != 0)
4456                 goto failed;
4457 
4458         if (nvlist_add_string(nvl, VRRP_EVENT_ROUTER_NAME, name) != 0)
4459                 goto failed;
4460 
4461         if (nvlist_add_uint8(nvl, VRRP_EVENT_STATE, st) != 0)
4462                 goto failed;
4463 
4464         if (nvlist_add_uint8(nvl, VRRP_EVENT_PREV_STATE, prev_st) != 0)
4465                 goto failed;
4466 
4467         if (sysevent_post_event(EC_VRRP, ESC_VRRP_STATE_CHANGE,
4468             SUNW_VENDOR, VRRP_EVENT_PUBLISHER, nvl, &eid) == 0) {
4469                 nvlist_free(nvl);
4470                 return (0);
4471         }
4472 
4473 failed:
4474         vrrp_log(VRRP_ERR, "vrrpd_post_event(): `state change (%s --> %s)' "
4475             "sysevent posting failed: %s", vrrp_state2str(prev_st),
4476             vrrp_state2str(st), strerror(errno));
4477 
4478         nvlist_free(nvl);
4479         return (-1);
4480 }
4481 
4482 /*
4483  * timeval processing functions
4484  */
4485 static int
4486 timeval_to_milli(struct timeval tv)
4487 {
4488         return ((int)(tv.tv_sec * 1000 + tv.tv_usec / 1000 + 0.5));
4489 }
4490 
4491 static struct timeval
4492 timeval_delta(struct timeval t1, struct timeval t2)
4493 {
4494         struct timeval t;
4495         t.tv_sec = t1.tv_sec - t2.tv_sec;
4496         t.tv_usec = t1.tv_usec - t2.tv_usec;
4497 
4498         if (t.tv_usec < 0) {
4499                 t.tv_usec += 1000000;
4500                 t.tv_sec--;
4501         }
4502         return (t);
4503 }
4504 
4505 /*
4506  * print error messages to the terminal or to syslog
4507  */
4508 static void
4509 vrrp_log(int level, char *message, ...)
4510 {
4511         va_list ap;
4512         int log_level = -1;
4513 
4514         va_start(ap, message);
4515 
4516         if (vrrp_logflag == 0) {
4517                 if (level <= vrrp_debug_level) {
4518                         /*
4519                          * VRRP_ERR goes to stderr, others go to stdout
4520                          */
4521                         FILE *out = (level <= VRRP_ERR) ? stderr : stdout;
4522                         (void) fprintf(out, "vrrpd: ");
4523                         /* LINTED: E_SEC_PRINTF_VAR_FMT */
4524                         (void) vfprintf(out, message, ap);
4525                         (void) fprintf(out, "\n");
4526                         (void) fflush(out);
4527                 }
4528                 va_end(ap);
4529                 return;
4530         }
4531 
4532         /*
4533          * translate VRRP_* to LOG_*
4534          */
4535         switch (level) {
4536         case VRRP_ERR:
4537                 log_level = LOG_ERR;
4538                 break;
4539         case VRRP_WARNING:
4540                 log_level = LOG_WARNING;
4541                 break;
4542         case VRRP_NOTICE:
4543                 log_level = LOG_NOTICE;
4544                 break;
4545         case VRRP_DBG0:
4546                 log_level = LOG_INFO;
4547                 break;
4548         default:
4549                 log_level = LOG_DEBUG;
4550                 break;
4551         }
4552 
4553         /* LINTED: E_SEC_PRINTF_VAR_FMT */
4554         (void) vsyslog(log_level, message, ap);
4555         va_end(ap);
4556 }