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