xref: /freebsd-13-stable/sbin/ifconfig/carp.c (revision 8ad303d68cec3ee1133550de37e0009502621e50)
1 /*	from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */
2 
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
7  * Copyright (c) 2003 Ryan McBride. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <sys/sockio.h>
35 
36 #include <stdlib.h>
37 #include <unistd.h>
38 
39 #include <net/if.h>
40 #include <netinet/in.h>
41 #include <netinet/in_var.h>
42 #include <netinet/ip_carp.h>
43 
44 #include <ctype.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <err.h>
50 #include <errno.h>
51 
52 #include <libifconfig.h>
53 
54 #include "ifconfig.h"
55 
56 static const char *carp_states[] = { CARP_STATES };
57 
58 static void carp_status(int s);
59 static void setcarp_vhid(const char *, int, int, const struct afswtch *rafp);
60 static void setcarp_callback(int, void *);
61 static void setcarp_advbase(const char *,int, int, const struct afswtch *rafp);
62 static void setcarp_advskew(const char *, int, int, const struct afswtch *rafp);
63 static void setcarp_passwd(const char *, int, int, const struct afswtch *rafp);
64 
65 static int carpr_vhid = -1;
66 static int carpr_advskew = -1;
67 static int carpr_advbase = -1;
68 static int carpr_state = -1;
69 static unsigned char const *carpr_key;
70 
71 static void
carp_status(int s)72 carp_status(int s)
73 {
74 	struct carpreq carpr[CARP_MAXVHID];
75 
76 	if (ifconfig_carp_get_info(lifh, name, carpr, CARP_MAXVHID) == -1)
77 		return;
78 
79 	for (size_t i = 0; i < carpr[0].carpr_count; i++) {
80 		printf("\tcarp: %s vhid %d advbase %d advskew %d",
81 		    carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid,
82 		    carpr[i].carpr_advbase, carpr[i].carpr_advskew);
83 		if (printkeys && carpr[i].carpr_key[0] != '\0')
84 			printf(" key \"%s\"\n", carpr[i].carpr_key);
85 		else
86 			printf("\n");
87 	}
88 }
89 
90 static void
setcarp_vhid(const char * val,int d,int s,const struct afswtch * afp)91 setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp)
92 {
93 
94 	carpr_vhid = atoi(val);
95 
96 	if (carpr_vhid <= 0 || carpr_vhid > CARP_MAXVHID)
97 		errx(1, "vhid must be greater than 0 and less than %u",
98 		    CARP_MAXVHID);
99 
100 	switch (afp->af_af) {
101 #ifdef INET
102 	case AF_INET:
103 	    {
104 		struct in_aliasreq *ifra;
105 
106 		ifra = (struct in_aliasreq *)afp->af_addreq;
107 		ifra->ifra_vhid = carpr_vhid;
108 		break;
109 	    }
110 #endif
111 #ifdef INET6
112 	case AF_INET6:
113 	    {
114 		struct in6_aliasreq *ifra;
115 
116 		ifra = (struct in6_aliasreq *)afp->af_addreq;
117 		ifra->ifra_vhid = carpr_vhid;
118 		break;
119 	    }
120 #endif
121 	default:
122 		errx(1, "%s doesn't support carp(4)", afp->af_name);
123 	}
124 
125 	callback_register(setcarp_callback, NULL);
126 }
127 
128 static void
setcarp_callback(int s,void * arg __unused)129 setcarp_callback(int s, void *arg __unused)
130 {
131 	struct carpreq carpr;
132 
133 	bzero(&carpr, sizeof(struct carpreq));
134 	carpr.carpr_vhid = carpr_vhid;
135 	carpr.carpr_count = 1;
136 	ifr.ifr_data = (caddr_t)&carpr;
137 
138 	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1 && errno != ENOENT)
139 		err(1, "SIOCGVH");
140 
141 	if (carpr_key != NULL)
142 		/* XXX Should hash the password into the key here? */
143 		strlcpy(carpr.carpr_key, carpr_key, CARP_KEY_LEN);
144 	if (carpr_advskew > -1)
145 		carpr.carpr_advskew = carpr_advskew;
146 	if (carpr_advbase > -1)
147 		carpr.carpr_advbase = carpr_advbase;
148 	if (carpr_state > -1)
149 		carpr.carpr_state = carpr_state;
150 
151 	if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
152 		err(1, "SIOCSVH");
153 }
154 
155 static void
setcarp_passwd(const char * val,int d,int s,const struct afswtch * afp)156 setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
157 {
158 
159 	if (carpr_vhid == -1)
160 		errx(1, "passwd requires vhid");
161 
162 	carpr_key = val;
163 }
164 
165 static void
setcarp_advskew(const char * val,int d,int s,const struct afswtch * afp)166 setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
167 {
168 
169 	if (carpr_vhid == -1)
170 		errx(1, "advskew requires vhid");
171 
172 	carpr_advskew = atoi(val);
173 }
174 
175 static void
setcarp_advbase(const char * val,int d,int s,const struct afswtch * afp)176 setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
177 {
178 
179 	if (carpr_vhid == -1)
180 		errx(1, "advbase requires vhid");
181 
182 	carpr_advbase = atoi(val);
183 }
184 
185 static void
setcarp_state(const char * val,int d,int s,const struct afswtch * afp)186 setcarp_state(const char *val, int d, int s, const struct afswtch *afp)
187 {
188 	int i;
189 
190 	if (carpr_vhid == -1)
191 		errx(1, "state requires vhid");
192 
193 	for (i = 0; i <= CARP_MAXSTATE; i++)
194 		if (strcasecmp(carp_states[i], val) == 0) {
195 			carpr_state = i;
196 			return;
197 		}
198 
199 	errx(1, "unknown state");
200 }
201 
202 static struct cmd carp_cmds[] = {
203 	DEF_CMD_ARG("advbase",	setcarp_advbase),
204 	DEF_CMD_ARG("advskew",	setcarp_advskew),
205 	DEF_CMD_ARG("pass",	setcarp_passwd),
206 	DEF_CMD_ARG("vhid",	setcarp_vhid),
207 	DEF_CMD_ARG("state",	setcarp_state),
208 };
209 static struct afswtch af_carp = {
210 	.af_name	= "af_carp",
211 	.af_af		= AF_UNSPEC,
212 	.af_other_status = carp_status,
213 };
214 
215 static __constructor void
carp_ctor(void)216 carp_ctor(void)
217 {
218 	int i;
219 
220 	for (i = 0; i < nitems(carp_cmds);  i++)
221 		cmd_register(&carp_cmds[i]);
222 	af_register(&af_carp);
223 }
224