1142215Sglebius/* $FreeBSD$ */ 2142215Sglebius/* from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */ 3142215Sglebius 4142215Sglebius/* 5142215Sglebius * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 6142215Sglebius * Copyright (c) 2003 Ryan McBride. All rights reserved. 7142215Sglebius * 8142215Sglebius * Redistribution and use in source and binary forms, with or without 9142215Sglebius * modification, are permitted provided that the following conditions 10142215Sglebius * are met: 11142215Sglebius * 1. Redistributions of source code must retain the above copyright 12142215Sglebius * notice, this list of conditions and the following disclaimer. 13142215Sglebius * 2. Redistributions in binary form must reproduce the above copyright 14142215Sglebius * notice, this list of conditions and the following disclaimer in the 15142215Sglebius * documentation and/or other materials provided with the distribution. 16142215Sglebius * 17142215Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18142215Sglebius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19142215Sglebius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20142215Sglebius * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 21142215Sglebius * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22142215Sglebius * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23142215Sglebius * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24142215Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25142215Sglebius * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26142215Sglebius * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27142215Sglebius * THE POSSIBILITY OF SUCH DAMAGE. 28142215Sglebius */ 29142215Sglebius 30142215Sglebius#include <sys/param.h> 31142215Sglebius#include <sys/ioctl.h> 32142215Sglebius#include <sys/socket.h> 33142215Sglebius#include <sys/sockio.h> 34142215Sglebius 35142215Sglebius#include <stdlib.h> 36142215Sglebius#include <unistd.h> 37142215Sglebius 38142215Sglebius#include <net/if.h> 39228571Sglebius#include <net/if_var.h> 40228571Sglebius#include <netinet/in.h> 41228571Sglebius#include <netinet/in_var.h> 42142215Sglebius#include <netinet/ip_carp.h> 43142215Sglebius 44142215Sglebius#include <ctype.h> 45142215Sglebius#include <stdio.h> 46142215Sglebius#include <string.h> 47142215Sglebius#include <stdlib.h> 48142215Sglebius#include <unistd.h> 49142215Sglebius#include <err.h> 50142215Sglebius#include <errno.h> 51142215Sglebius 52142215Sglebius#include "ifconfig.h" 53142215Sglebius 54142215Sglebiusstatic const char *carp_states[] = { CARP_STATES }; 55142215Sglebius 56228571Sglebiusstatic void carp_status(int s); 57228571Sglebiusstatic void setcarp_vhid(const char *, int, int, const struct afswtch *rafp); 58228571Sglebiusstatic void setcarp_callback(int, void *); 59228571Sglebiusstatic void setcarp_advbase(const char *,int, int, const struct afswtch *rafp); 60228571Sglebiusstatic void setcarp_advskew(const char *, int, int, const struct afswtch *rafp); 61228571Sglebiusstatic void setcarp_passwd(const char *, int, int, const struct afswtch *rafp); 62142215Sglebius 63228571Sglebiusstatic int carpr_vhid = -1; 64228571Sglebiusstatic int carpr_advskew = -1; 65228571Sglebiusstatic int carpr_advbase = -1; 66228571Sglebiusstatic int carpr_state = -1; 67228571Sglebiusstatic unsigned char const *carpr_key; 68228571Sglebius 69228571Sglebiusstatic void 70142224Sglebiuscarp_status(int s) 71142215Sglebius{ 72228571Sglebius struct carpreq carpr[CARP_MAXVHID]; 73228571Sglebius int i; 74142215Sglebius 75228571Sglebius bzero(carpr, sizeof(struct carpreq) * CARP_MAXVHID); 76228571Sglebius carpr[0].carpr_count = CARP_MAXVHID; 77142215Sglebius ifr.ifr_data = (caddr_t)&carpr; 78142215Sglebius 79142215Sglebius if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 80142215Sglebius return; 81142215Sglebius 82228571Sglebius for (i = 0; i < carpr[0].carpr_count; i++) { 83228571Sglebius printf("\tcarp: %s vhid %d advbase %d advskew %d", 84228571Sglebius carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid, 85228571Sglebius carpr[i].carpr_advbase, carpr[i].carpr_advskew); 86228571Sglebius if (printkeys && carpr[i].carpr_key[0] != '\0') 87228571Sglebius printf(" key \"%s\"\n", carpr[i].carpr_key); 88142215Sglebius else 89228571Sglebius printf("\n"); 90142215Sglebius } 91142215Sglebius} 92142215Sglebius 93228571Sglebiusstatic void 94228571Sglebiussetcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) 95142215Sglebius{ 96142215Sglebius 97228571Sglebius carpr_vhid = atoi(val); 98142215Sglebius 99228571Sglebius if (carpr_vhid <= 0 || carpr_vhid > CARP_MAXVHID) 100228571Sglebius errx(1, "vhid must be greater than 0 and less than %u", 101228571Sglebius CARP_MAXVHID); 102142215Sglebius 103228571Sglebius switch (afp->af_af) { 104228571Sglebius#ifdef INET 105228571Sglebius case AF_INET: 106228571Sglebius { 107228571Sglebius struct in_aliasreq *ifra; 108142215Sglebius 109228571Sglebius ifra = (struct in_aliasreq *)afp->af_addreq; 110228571Sglebius ifra->ifra_vhid = carpr_vhid; 111228571Sglebius break; 112228571Sglebius } 113228571Sglebius#endif 114228571Sglebius#ifdef INET6 115228571Sglebius case AF_INET6: 116228571Sglebius { 117228571Sglebius struct in6_aliasreq *ifra; 118142215Sglebius 119228571Sglebius ifra = (struct in6_aliasreq *)afp->af_addreq; 120228571Sglebius ifra->ifra_vhid = carpr_vhid; 121228571Sglebius break; 122228571Sglebius } 123228571Sglebius#endif 124228571Sglebius default: 125228571Sglebius errx(1, "%s doesn't support carp(4)", afp->af_name); 126228571Sglebius } 127228571Sglebius 128228571Sglebius callback_register(setcarp_callback, NULL); 129142215Sglebius} 130142215Sglebius 131228571Sglebiusstatic void 132228571Sglebiussetcarp_callback(int s, void *arg __unused) 133142215Sglebius{ 134142215Sglebius struct carpreq carpr; 135142215Sglebius 136228571Sglebius bzero(&carpr, sizeof(struct carpreq)); 137228571Sglebius carpr.carpr_vhid = carpr_vhid; 138228571Sglebius carpr.carpr_count = 1; 139142215Sglebius ifr.ifr_data = (caddr_t)&carpr; 140142215Sglebius 141228571Sglebius if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1 && errno != ENOENT) 142142215Sglebius err(1, "SIOCGVH"); 143142215Sglebius 144228571Sglebius if (carpr_key != NULL) 145228571Sglebius /* XXX Should hash the password into the key here? */ 146228571Sglebius strlcpy(carpr.carpr_key, carpr_key, CARP_KEY_LEN); 147228571Sglebius if (carpr_advskew > -1) 148228571Sglebius carpr.carpr_advskew = carpr_advskew; 149228571Sglebius if (carpr_advbase > -1) 150228571Sglebius carpr.carpr_advbase = carpr_advbase; 151228571Sglebius if (carpr_state > -1) 152228571Sglebius carpr.carpr_state = carpr_state; 153142215Sglebius 154142215Sglebius if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 155142215Sglebius err(1, "SIOCSVH"); 156142215Sglebius} 157142215Sglebius 158228571Sglebiusstatic void 159228571Sglebiussetcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) 160142215Sglebius{ 161142215Sglebius 162228571Sglebius if (carpr_vhid == -1) 163228571Sglebius errx(1, "passwd requires vhid"); 164142215Sglebius 165228571Sglebius carpr_key = val; 166228571Sglebius} 167142215Sglebius 168228571Sglebiusstatic void 169228571Sglebiussetcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) 170228571Sglebius{ 171142215Sglebius 172228571Sglebius if (carpr_vhid == -1) 173228571Sglebius errx(1, "advskew requires vhid"); 174142215Sglebius 175228571Sglebius carpr_advskew = atoi(val); 176142215Sglebius} 177142215Sglebius 178228571Sglebiusstatic void 179142215Sglebiussetcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) 180142215Sglebius{ 181142215Sglebius 182228571Sglebius if (carpr_vhid == -1) 183228571Sglebius errx(1, "advbase requires vhid"); 184142215Sglebius 185228571Sglebius carpr_advbase = atoi(val); 186228571Sglebius} 187142215Sglebius 188228571Sglebiusstatic void 189228571Sglebiussetcarp_state(const char *val, int d, int s, const struct afswtch *afp) 190228571Sglebius{ 191228571Sglebius int i; 192142215Sglebius 193228571Sglebius if (carpr_vhid == -1) 194228571Sglebius errx(1, "state requires vhid"); 195142215Sglebius 196228571Sglebius for (i = 0; i <= CARP_MAXSTATE; i++) 197228571Sglebius if (strcasecmp(carp_states[i], val) == 0) { 198228571Sglebius carpr_state = i; 199228571Sglebius return; 200228571Sglebius } 201142215Sglebius 202228571Sglebius errx(1, "unknown state"); 203142215Sglebius} 204142215Sglebius 205142215Sglebiusstatic struct cmd carp_cmds[] = { 206142215Sglebius DEF_CMD_ARG("advbase", setcarp_advbase), 207142215Sglebius DEF_CMD_ARG("advskew", setcarp_advskew), 208142215Sglebius DEF_CMD_ARG("pass", setcarp_passwd), 209142215Sglebius DEF_CMD_ARG("vhid", setcarp_vhid), 210228571Sglebius DEF_CMD_ARG("state", setcarp_state), 211142215Sglebius}; 212142215Sglebiusstatic struct afswtch af_carp = { 213142215Sglebius .af_name = "af_carp", 214142215Sglebius .af_af = AF_UNSPEC, 215142224Sglebius .af_other_status = carp_status, 216142215Sglebius}; 217142215Sglebius 218142215Sglebiusstatic __constructor void 219142215Sglebiuscarp_ctor(void) 220142215Sglebius{ 221142215Sglebius int i; 222142215Sglebius 223289986Sngie for (i = 0; i < nitems(carp_cmds); i++) 224142215Sglebius cmd_register(&carp_cmds[i]); 225142215Sglebius af_register(&af_carp); 226142215Sglebius} 227