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