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