xref: /minix3/sbin/ifconfig/carp.c (revision 90b801219a391518dca4b04b17c88ad3b82b6ad9)
1*90b80121SDavid van Moolenbroek /* $NetBSD: carp.c,v 1.13 2009/09/11 23:22:28 dyoung Exp $ */
2*90b80121SDavid van Moolenbroek 
3*90b80121SDavid van Moolenbroek /*
4*90b80121SDavid van Moolenbroek  * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
5*90b80121SDavid van Moolenbroek  * Copyright (c) 2003 Ryan McBride. All rights reserved.
6*90b80121SDavid van Moolenbroek  *
7*90b80121SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
8*90b80121SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
9*90b80121SDavid van Moolenbroek  * are met:
10*90b80121SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
11*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
12*90b80121SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
13*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
14*90b80121SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
15*90b80121SDavid van Moolenbroek  *
16*90b80121SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*90b80121SDavid van Moolenbroek  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*90b80121SDavid van Moolenbroek  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*90b80121SDavid van Moolenbroek  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20*90b80121SDavid van Moolenbroek  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*90b80121SDavid van Moolenbroek  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*90b80121SDavid van Moolenbroek  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*90b80121SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24*90b80121SDavid van Moolenbroek  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25*90b80121SDavid van Moolenbroek  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26*90b80121SDavid van Moolenbroek  * THE POSSIBILITY OF SUCH DAMAGE.
27*90b80121SDavid van Moolenbroek  */
28*90b80121SDavid van Moolenbroek 
29*90b80121SDavid van Moolenbroek #include <sys/cdefs.h>
30*90b80121SDavid van Moolenbroek #ifndef lint
31*90b80121SDavid van Moolenbroek __RCSID("$NetBSD: carp.c,v 1.13 2009/09/11 23:22:28 dyoung Exp $");
32*90b80121SDavid van Moolenbroek #endif /* not lint */
33*90b80121SDavid van Moolenbroek 
34*90b80121SDavid van Moolenbroek #include <sys/param.h>
35*90b80121SDavid van Moolenbroek #include <sys/ioctl.h>
36*90b80121SDavid van Moolenbroek #include <sys/socket.h>
37*90b80121SDavid van Moolenbroek #include <sys/sockio.h>
38*90b80121SDavid van Moolenbroek 
39*90b80121SDavid van Moolenbroek #include <net/if.h>
40*90b80121SDavid van Moolenbroek #include <netinet/ip_carp.h>
41*90b80121SDavid van Moolenbroek #include <net/route.h>
42*90b80121SDavid van Moolenbroek 
43*90b80121SDavid van Moolenbroek #include <stdio.h>
44*90b80121SDavid van Moolenbroek #include <string.h>
45*90b80121SDavid van Moolenbroek #include <stdlib.h>
46*90b80121SDavid van Moolenbroek #include <unistd.h>
47*90b80121SDavid van Moolenbroek #include <err.h>
48*90b80121SDavid van Moolenbroek #include <errno.h>
49*90b80121SDavid van Moolenbroek #include <util.h>
50*90b80121SDavid van Moolenbroek 
51*90b80121SDavid van Moolenbroek #include "env.h"
52*90b80121SDavid van Moolenbroek #include "parse.h"
53*90b80121SDavid van Moolenbroek #include "extern.h"
54*90b80121SDavid van Moolenbroek 
55*90b80121SDavid van Moolenbroek static status_func_t status;
56*90b80121SDavid van Moolenbroek static usage_func_t usage;
57*90b80121SDavid van Moolenbroek static cmdloop_branch_t branch;
58*90b80121SDavid van Moolenbroek 
59*90b80121SDavid van Moolenbroek static void carp_constructor(void) __attribute__((constructor));
60*90b80121SDavid van Moolenbroek static void carp_status(prop_dictionary_t, prop_dictionary_t);
61*90b80121SDavid van Moolenbroek static int setcarp_advbase(prop_dictionary_t, prop_dictionary_t);
62*90b80121SDavid van Moolenbroek static int setcarp_advskew(prop_dictionary_t, prop_dictionary_t);
63*90b80121SDavid van Moolenbroek static int setcarp_passwd(prop_dictionary_t, prop_dictionary_t);
64*90b80121SDavid van Moolenbroek static int setcarp_vhid(prop_dictionary_t, prop_dictionary_t);
65*90b80121SDavid van Moolenbroek static int setcarp_state(prop_dictionary_t, prop_dictionary_t);
66*90b80121SDavid van Moolenbroek static int setcarpdev(prop_dictionary_t, prop_dictionary_t);
67*90b80121SDavid van Moolenbroek 
68*90b80121SDavid van Moolenbroek static const char *carp_states[] = { CARP_STATES };
69*90b80121SDavid van Moolenbroek 
70*90b80121SDavid van Moolenbroek struct kwinst carpstatekw[] = {
71*90b80121SDavid van Moolenbroek 	  {.k_word = "INIT", .k_nextparser = &command_root.pb_parser}
72*90b80121SDavid van Moolenbroek 	, {.k_word = "BACKUP", .k_nextparser = &command_root.pb_parser}
73*90b80121SDavid van Moolenbroek 	, {.k_word = "MASTER", .k_nextparser = &command_root.pb_parser}
74*90b80121SDavid van Moolenbroek };
75*90b80121SDavid van Moolenbroek 
76*90b80121SDavid van Moolenbroek struct pinteger parse_advbase = PINTEGER_INITIALIZER1(&parse_advbase, "advbase",
77*90b80121SDavid van Moolenbroek     0, 255, 10, setcarp_advbase, "advbase", &command_root.pb_parser);
78*90b80121SDavid van Moolenbroek 
79*90b80121SDavid van Moolenbroek struct pinteger parse_advskew = PINTEGER_INITIALIZER1(&parse_advskew, "advskew",
80*90b80121SDavid van Moolenbroek     0, 254, 10, setcarp_advskew, "advskew", &command_root.pb_parser);
81*90b80121SDavid van Moolenbroek 
82*90b80121SDavid van Moolenbroek struct piface carpdev = PIFACE_INITIALIZER(&carpdev, "carpdev", setcarpdev,
83*90b80121SDavid van Moolenbroek     "carpdev", &command_root.pb_parser);
84*90b80121SDavid van Moolenbroek 
85*90b80121SDavid van Moolenbroek struct pkw carpstate = PKW_INITIALIZER(&carpstate, "carp state", setcarp_state,
86*90b80121SDavid van Moolenbroek     "carp_state", carpstatekw, __arraycount(carpstatekw),
87*90b80121SDavid van Moolenbroek     &command_root.pb_parser);
88*90b80121SDavid van Moolenbroek 
89*90b80121SDavid van Moolenbroek struct pstr pass = PSTR_INITIALIZER(&pass, "pass", setcarp_passwd,
90*90b80121SDavid van Moolenbroek     "pass", &command_root.pb_parser);
91*90b80121SDavid van Moolenbroek 
92*90b80121SDavid van Moolenbroek struct pinteger parse_vhid = PINTEGER_INITIALIZER1(&vhid, "vhid",
93*90b80121SDavid van Moolenbroek     0, 255, 10, setcarp_vhid, "vhid", &command_root.pb_parser);
94*90b80121SDavid van Moolenbroek 
95*90b80121SDavid van Moolenbroek static const struct kwinst carpkw[] = {
96*90b80121SDavid van Moolenbroek 	  {.k_word = "advbase", .k_nextparser = &parse_advbase.pi_parser}
97*90b80121SDavid van Moolenbroek 	, {.k_word = "advskew", .k_nextparser = &parse_advskew.pi_parser}
98*90b80121SDavid van Moolenbroek 	, {.k_word = "carpdev", .k_nextparser = &carpdev.pif_parser}
99*90b80121SDavid van Moolenbroek 	, {.k_word = "-carpdev", .k_key = "carpdev", .k_type = KW_T_STR,
100*90b80121SDavid van Moolenbroek 	   .k_str = "", .k_exec = setcarpdev,
101*90b80121SDavid van Moolenbroek 	   .k_nextparser = &command_root.pb_parser}
102*90b80121SDavid van Moolenbroek 	, {.k_word = "pass", .k_nextparser = &pass.ps_parser}
103*90b80121SDavid van Moolenbroek 	, {.k_word = "state", .k_nextparser = &carpstate.pk_parser}
104*90b80121SDavid van Moolenbroek 	, {.k_word = "vhid", .k_nextparser = &parse_vhid.pi_parser}
105*90b80121SDavid van Moolenbroek };
106*90b80121SDavid van Moolenbroek 
107*90b80121SDavid van Moolenbroek struct pkw carp = PKW_INITIALIZER(&carp, "CARP", NULL, NULL,
108*90b80121SDavid van Moolenbroek     carpkw, __arraycount(carpkw), NULL);
109*90b80121SDavid van Moolenbroek 
110*90b80121SDavid van Moolenbroek static void
carp_set(prop_dictionary_t env,struct carpreq * carpr)111*90b80121SDavid van Moolenbroek carp_set(prop_dictionary_t env, struct carpreq *carpr)
112*90b80121SDavid van Moolenbroek {
113*90b80121SDavid van Moolenbroek 	if (indirect_ioctl(env, SIOCSVH, carpr) == -1)
114*90b80121SDavid van Moolenbroek 		err(EXIT_FAILURE, "SIOCSVH");
115*90b80121SDavid van Moolenbroek }
116*90b80121SDavid van Moolenbroek 
117*90b80121SDavid van Moolenbroek static int
carp_get1(prop_dictionary_t env,struct carpreq * carpr)118*90b80121SDavid van Moolenbroek carp_get1(prop_dictionary_t env, struct carpreq *carpr)
119*90b80121SDavid van Moolenbroek {
120*90b80121SDavid van Moolenbroek 	memset(carpr, 0, sizeof(*carpr));
121*90b80121SDavid van Moolenbroek 
122*90b80121SDavid van Moolenbroek 	return indirect_ioctl(env, SIOCGVH, carpr);
123*90b80121SDavid van Moolenbroek }
124*90b80121SDavid van Moolenbroek 
125*90b80121SDavid van Moolenbroek static void
carp_get(prop_dictionary_t env,struct carpreq * carpr)126*90b80121SDavid van Moolenbroek carp_get(prop_dictionary_t env, struct carpreq *carpr)
127*90b80121SDavid van Moolenbroek {
128*90b80121SDavid van Moolenbroek 	if (carp_get1(env, carpr) == -1)
129*90b80121SDavid van Moolenbroek 		err(EXIT_FAILURE, "SIOCGVH");
130*90b80121SDavid van Moolenbroek }
131*90b80121SDavid van Moolenbroek 
132*90b80121SDavid van Moolenbroek static void
carp_status(prop_dictionary_t env,prop_dictionary_t oenv)133*90b80121SDavid van Moolenbroek carp_status(prop_dictionary_t env, prop_dictionary_t oenv)
134*90b80121SDavid van Moolenbroek {
135*90b80121SDavid van Moolenbroek 	const char *state;
136*90b80121SDavid van Moolenbroek 	struct carpreq carpr;
137*90b80121SDavid van Moolenbroek 
138*90b80121SDavid van Moolenbroek 	if (carp_get1(env, &carpr) == -1)
139*90b80121SDavid van Moolenbroek 		return;
140*90b80121SDavid van Moolenbroek 
141*90b80121SDavid van Moolenbroek 	if (carpr.carpr_vhid <= 0)
142*90b80121SDavid van Moolenbroek 		return;
143*90b80121SDavid van Moolenbroek 	if (carpr.carpr_state > CARP_MAXSTATE)
144*90b80121SDavid van Moolenbroek 		state = "<UNKNOWN>";
145*90b80121SDavid van Moolenbroek 	else
146*90b80121SDavid van Moolenbroek 		state = carp_states[carpr.carpr_state];
147*90b80121SDavid van Moolenbroek 
148*90b80121SDavid van Moolenbroek 	printf("\tcarp: %s carpdev %s vhid %d advbase %d advskew %d\n",
149*90b80121SDavid van Moolenbroek 	    state, carpr.carpr_carpdev[0] != '\0' ?
150*90b80121SDavid van Moolenbroek 	    carpr.carpr_carpdev : "none", carpr.carpr_vhid,
151*90b80121SDavid van Moolenbroek 	    carpr.carpr_advbase, carpr.carpr_advskew);
152*90b80121SDavid van Moolenbroek }
153*90b80121SDavid van Moolenbroek 
154*90b80121SDavid van Moolenbroek int
setcarp_passwd(prop_dictionary_t env,prop_dictionary_t oenv)155*90b80121SDavid van Moolenbroek setcarp_passwd(prop_dictionary_t env, prop_dictionary_t oenv)
156*90b80121SDavid van Moolenbroek {
157*90b80121SDavid van Moolenbroek 	struct carpreq carpr;
158*90b80121SDavid van Moolenbroek 	prop_data_t data;
159*90b80121SDavid van Moolenbroek 
160*90b80121SDavid van Moolenbroek 	data = (prop_data_t)prop_dictionary_get(env, "pass");
161*90b80121SDavid van Moolenbroek 	if (data == NULL) {
162*90b80121SDavid van Moolenbroek 		errno = ENOENT;
163*90b80121SDavid van Moolenbroek 		return -1;
164*90b80121SDavid van Moolenbroek 	}
165*90b80121SDavid van Moolenbroek 
166*90b80121SDavid van Moolenbroek 	carp_get(env, &carpr);
167*90b80121SDavid van Moolenbroek 
168*90b80121SDavid van Moolenbroek 	memset(carpr.carpr_key, 0, sizeof(carpr.carpr_key));
169*90b80121SDavid van Moolenbroek 	/* XXX Should hash the password into the key here, perhaps? */
170*90b80121SDavid van Moolenbroek 	strlcpy((char *)carpr.carpr_key, prop_data_data_nocopy(data),
171*90b80121SDavid van Moolenbroek 	    MIN(CARP_KEY_LEN, prop_data_size(data)));
172*90b80121SDavid van Moolenbroek 
173*90b80121SDavid van Moolenbroek 	carp_set(env, &carpr);
174*90b80121SDavid van Moolenbroek 	return 0;
175*90b80121SDavid van Moolenbroek }
176*90b80121SDavid van Moolenbroek 
177*90b80121SDavid van Moolenbroek int
setcarp_vhid(prop_dictionary_t env,prop_dictionary_t oenv)178*90b80121SDavid van Moolenbroek setcarp_vhid(prop_dictionary_t env, prop_dictionary_t oenv)
179*90b80121SDavid van Moolenbroek {
180*90b80121SDavid van Moolenbroek 	struct carpreq carpr;
181*90b80121SDavid van Moolenbroek 	int64_t vhid;
182*90b80121SDavid van Moolenbroek 
183*90b80121SDavid van Moolenbroek 	if (!prop_dictionary_get_int64(env, "vhid", &vhid)) {
184*90b80121SDavid van Moolenbroek 		errno = ENOENT;
185*90b80121SDavid van Moolenbroek 		return -1;
186*90b80121SDavid van Moolenbroek 	}
187*90b80121SDavid van Moolenbroek 
188*90b80121SDavid van Moolenbroek 	carp_get(env, &carpr);
189*90b80121SDavid van Moolenbroek 
190*90b80121SDavid van Moolenbroek 	carpr.carpr_vhid = vhid;
191*90b80121SDavid van Moolenbroek 
192*90b80121SDavid van Moolenbroek 	carp_set(env, &carpr);
193*90b80121SDavid van Moolenbroek 	return 0;
194*90b80121SDavid van Moolenbroek }
195*90b80121SDavid van Moolenbroek 
196*90b80121SDavid van Moolenbroek int
setcarp_advskew(prop_dictionary_t env,prop_dictionary_t oenv)197*90b80121SDavid van Moolenbroek setcarp_advskew(prop_dictionary_t env, prop_dictionary_t oenv)
198*90b80121SDavid van Moolenbroek {
199*90b80121SDavid van Moolenbroek 	struct carpreq carpr;
200*90b80121SDavid van Moolenbroek 	int64_t advskew;
201*90b80121SDavid van Moolenbroek 
202*90b80121SDavid van Moolenbroek 	if (!prop_dictionary_get_int64(env, "advskew", &advskew)) {
203*90b80121SDavid van Moolenbroek 		errno = ENOENT;
204*90b80121SDavid van Moolenbroek 		return -1;
205*90b80121SDavid van Moolenbroek 	}
206*90b80121SDavid van Moolenbroek 
207*90b80121SDavid van Moolenbroek 	carp_get(env, &carpr);
208*90b80121SDavid van Moolenbroek 
209*90b80121SDavid van Moolenbroek 	carpr.carpr_advskew = advskew;
210*90b80121SDavid van Moolenbroek 
211*90b80121SDavid van Moolenbroek 	carp_set(env, &carpr);
212*90b80121SDavid van Moolenbroek 	return 0;
213*90b80121SDavid van Moolenbroek }
214*90b80121SDavid van Moolenbroek 
215*90b80121SDavid van Moolenbroek /* ARGSUSED */
216*90b80121SDavid van Moolenbroek int
setcarp_advbase(prop_dictionary_t env,prop_dictionary_t oenv)217*90b80121SDavid van Moolenbroek setcarp_advbase(prop_dictionary_t env, prop_dictionary_t oenv)
218*90b80121SDavid van Moolenbroek {
219*90b80121SDavid van Moolenbroek 	struct carpreq carpr;
220*90b80121SDavid van Moolenbroek 	int64_t advbase;
221*90b80121SDavid van Moolenbroek 
222*90b80121SDavid van Moolenbroek 	if (!prop_dictionary_get_int64(env, "advbase", &advbase)) {
223*90b80121SDavid van Moolenbroek 		errno = ENOENT;
224*90b80121SDavid van Moolenbroek 		return -1;
225*90b80121SDavid van Moolenbroek 	}
226*90b80121SDavid van Moolenbroek 
227*90b80121SDavid van Moolenbroek 	carp_get(env, &carpr);
228*90b80121SDavid van Moolenbroek 
229*90b80121SDavid van Moolenbroek 	carpr.carpr_advbase = advbase;
230*90b80121SDavid van Moolenbroek 
231*90b80121SDavid van Moolenbroek 	carp_set(env, &carpr);
232*90b80121SDavid van Moolenbroek 	return 0;
233*90b80121SDavid van Moolenbroek }
234*90b80121SDavid van Moolenbroek 
235*90b80121SDavid van Moolenbroek /* ARGSUSED */
236*90b80121SDavid van Moolenbroek static int
setcarp_state(prop_dictionary_t env,prop_dictionary_t oenv)237*90b80121SDavid van Moolenbroek setcarp_state(prop_dictionary_t env, prop_dictionary_t oenv)
238*90b80121SDavid van Moolenbroek {
239*90b80121SDavid van Moolenbroek 	struct carpreq carpr;
240*90b80121SDavid van Moolenbroek 	int64_t carp_state;
241*90b80121SDavid van Moolenbroek 
242*90b80121SDavid van Moolenbroek 	if (!prop_dictionary_get_int64(env, "carp_state", &carp_state)) {
243*90b80121SDavid van Moolenbroek 		errno = ENOENT;
244*90b80121SDavid van Moolenbroek 		return -1;
245*90b80121SDavid van Moolenbroek 	}
246*90b80121SDavid van Moolenbroek 
247*90b80121SDavid van Moolenbroek 	carp_get(env, &carpr);
248*90b80121SDavid van Moolenbroek 
249*90b80121SDavid van Moolenbroek 	carpr.carpr_state = carp_state;
250*90b80121SDavid van Moolenbroek 
251*90b80121SDavid van Moolenbroek 	carp_set(env, &carpr);
252*90b80121SDavid van Moolenbroek 	return 0;
253*90b80121SDavid van Moolenbroek }
254*90b80121SDavid van Moolenbroek 
255*90b80121SDavid van Moolenbroek /* ARGSUSED */
256*90b80121SDavid van Moolenbroek int
setcarpdev(prop_dictionary_t env,prop_dictionary_t oenv)257*90b80121SDavid van Moolenbroek setcarpdev(prop_dictionary_t env, prop_dictionary_t oenv)
258*90b80121SDavid van Moolenbroek {
259*90b80121SDavid van Moolenbroek 	struct carpreq carpr;
260*90b80121SDavid van Moolenbroek 	prop_string_t s;
261*90b80121SDavid van Moolenbroek 
262*90b80121SDavid van Moolenbroek 	s = (prop_string_t)prop_dictionary_get(env, "carpdev");
263*90b80121SDavid van Moolenbroek 	if (s == NULL) {
264*90b80121SDavid van Moolenbroek 		errno = ENOENT;
265*90b80121SDavid van Moolenbroek 		return -1;
266*90b80121SDavid van Moolenbroek 	}
267*90b80121SDavid van Moolenbroek 
268*90b80121SDavid van Moolenbroek 	carp_get(env, &carpr);
269*90b80121SDavid van Moolenbroek 
270*90b80121SDavid van Moolenbroek 	strlcpy(carpr.carpr_carpdev, prop_string_cstring_nocopy(s),
271*90b80121SDavid van Moolenbroek 	    sizeof(carpr.carpr_carpdev));
272*90b80121SDavid van Moolenbroek 
273*90b80121SDavid van Moolenbroek 	carp_set(env, &carpr);
274*90b80121SDavid van Moolenbroek 	return 0;
275*90b80121SDavid van Moolenbroek }
276*90b80121SDavid van Moolenbroek 
277*90b80121SDavid van Moolenbroek static void
carp_usage(prop_dictionary_t env)278*90b80121SDavid van Moolenbroek carp_usage(prop_dictionary_t env)
279*90b80121SDavid van Moolenbroek {
280*90b80121SDavid van Moolenbroek 	fprintf(stderr,
281*90b80121SDavid van Moolenbroek 	    "\t[ advbase n ] [ advskew n ] [ carpdev iface ] "
282*90b80121SDavid van Moolenbroek 	    "[ pass passphrase ] [ state state ] [ vhid n ]\n");
283*90b80121SDavid van Moolenbroek 
284*90b80121SDavid van Moolenbroek }
285*90b80121SDavid van Moolenbroek 
286*90b80121SDavid van Moolenbroek static void
carp_constructor(void)287*90b80121SDavid van Moolenbroek carp_constructor(void)
288*90b80121SDavid van Moolenbroek {
289*90b80121SDavid van Moolenbroek 	cmdloop_branch_init(&branch, &carp.pk_parser);
290*90b80121SDavid van Moolenbroek 	register_cmdloop_branch(&branch);
291*90b80121SDavid van Moolenbroek 	status_func_init(&status, carp_status);
292*90b80121SDavid van Moolenbroek 	usage_func_init(&usage, carp_usage);
293*90b80121SDavid van Moolenbroek 	register_status(&status);
294*90b80121SDavid van Moolenbroek 	register_usage(&usage);
295*90b80121SDavid van Moolenbroek }
296