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