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