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