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