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