15f024827SGleb Smirnoff /* $FreeBSD$ */ 25f024827SGleb Smirnoff /* from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */ 35f024827SGleb Smirnoff 41de7b4b8SPedro F. Giffuni /*- 51de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 61de7b4b8SPedro F. Giffuni * 75f024827SGleb Smirnoff * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 85f024827SGleb Smirnoff * Copyright (c) 2003 Ryan McBride. All rights reserved. 95f024827SGleb Smirnoff * 105f024827SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 115f024827SGleb Smirnoff * modification, are permitted provided that the following conditions 125f024827SGleb Smirnoff * are met: 135f024827SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 145f024827SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 155f024827SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 165f024827SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 175f024827SGleb Smirnoff * documentation and/or other materials provided with the distribution. 185f024827SGleb Smirnoff * 195f024827SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 205f024827SGleb Smirnoff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 215f024827SGleb Smirnoff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 225f024827SGleb Smirnoff * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 235f024827SGleb Smirnoff * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 245f024827SGleb Smirnoff * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 255f024827SGleb Smirnoff * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 265f024827SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 275f024827SGleb Smirnoff * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 285f024827SGleb Smirnoff * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 295f024827SGleb Smirnoff * THE POSSIBILITY OF SUCH DAMAGE. 305f024827SGleb Smirnoff */ 315f024827SGleb Smirnoff 325f024827SGleb Smirnoff #include <sys/param.h> 335f024827SGleb Smirnoff #include <sys/ioctl.h> 345f024827SGleb Smirnoff #include <sys/socket.h> 355f024827SGleb Smirnoff #include <sys/sockio.h> 365f024827SGleb Smirnoff 375f024827SGleb Smirnoff #include <stdlib.h> 385f024827SGleb Smirnoff #include <unistd.h> 395f024827SGleb Smirnoff 405f024827SGleb Smirnoff #include <net/if.h> 415f024827SGleb Smirnoff #include <netinet/in.h> 425f024827SGleb Smirnoff #include <netinet/in_var.h> 435f024827SGleb Smirnoff #include <netinet/ip_carp.h> 445f024827SGleb Smirnoff 455f024827SGleb Smirnoff #include <ctype.h> 465f024827SGleb Smirnoff #include <stdio.h> 475f024827SGleb Smirnoff #include <string.h> 485f024827SGleb Smirnoff #include <stdlib.h> 495f024827SGleb Smirnoff #include <unistd.h> 505f024827SGleb Smirnoff #include <err.h> 515f024827SGleb Smirnoff #include <errno.h> 525f024827SGleb Smirnoff 53*da393346SRyan Moeller #include <libifconfig.h> 54*da393346SRyan Moeller 555f024827SGleb Smirnoff #include "ifconfig.h" 565f024827SGleb Smirnoff 575f024827SGleb Smirnoff static const char *carp_states[] = { CARP_STATES }; 585f024827SGleb Smirnoff 595f024827SGleb Smirnoff static void carp_status(int s); 605f024827SGleb Smirnoff static void setcarp_vhid(const char *, int, int, const struct afswtch *rafp); 615f024827SGleb Smirnoff static void setcarp_callback(int, void *); 625f024827SGleb Smirnoff static void setcarp_advbase(const char *,int, int, const struct afswtch *rafp); 635f024827SGleb Smirnoff static void setcarp_advskew(const char *, int, int, const struct afswtch *rafp); 645f024827SGleb Smirnoff static void setcarp_passwd(const char *, int, int, const struct afswtch *rafp); 655f024827SGleb Smirnoff 665f024827SGleb Smirnoff static int carpr_vhid = -1; 675f024827SGleb Smirnoff static int carpr_advskew = -1; 685f024827SGleb Smirnoff static int carpr_advbase = -1; 695f024827SGleb Smirnoff static int carpr_state = -1; 705f024827SGleb Smirnoff static unsigned char const *carpr_key; 715f024827SGleb Smirnoff 725f024827SGleb Smirnoff static void 735f024827SGleb Smirnoff carp_status(int s) 745f024827SGleb Smirnoff { 755f024827SGleb Smirnoff struct carpreq carpr[CARP_MAXVHID]; 76*da393346SRyan Moeller ifconfig_handle_t *lifh; 775f024827SGleb Smirnoff 78*da393346SRyan Moeller lifh = ifconfig_open(); 79*da393346SRyan Moeller if (lifh == NULL) 805f024827SGleb Smirnoff return; 815f024827SGleb Smirnoff 82*da393346SRyan Moeller if (ifconfig_carp_get_info(lifh, name, carpr, CARP_MAXVHID) == -1) 83*da393346SRyan Moeller goto close; 84*da393346SRyan Moeller 85*da393346SRyan Moeller for (size_t i = 0; i < carpr[0].carpr_count; i++) { 865f024827SGleb Smirnoff printf("\tcarp: %s vhid %d advbase %d advskew %d", 875f024827SGleb Smirnoff carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid, 885f024827SGleb Smirnoff carpr[i].carpr_advbase, carpr[i].carpr_advskew); 895f024827SGleb Smirnoff if (printkeys && carpr[i].carpr_key[0] != '\0') 905f024827SGleb Smirnoff printf(" key \"%s\"\n", carpr[i].carpr_key); 915f024827SGleb Smirnoff else 925f024827SGleb Smirnoff printf("\n"); 935f024827SGleb Smirnoff } 94*da393346SRyan Moeller close: 95*da393346SRyan Moeller ifconfig_close(lifh); 965f024827SGleb Smirnoff } 975f024827SGleb Smirnoff 985f024827SGleb Smirnoff static void 995f024827SGleb Smirnoff setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) 1005f024827SGleb Smirnoff { 1015f024827SGleb Smirnoff 1025f024827SGleb Smirnoff carpr_vhid = atoi(val); 1035f024827SGleb Smirnoff 1045f024827SGleb Smirnoff if (carpr_vhid <= 0 || carpr_vhid > CARP_MAXVHID) 1055f024827SGleb Smirnoff errx(1, "vhid must be greater than 0 and less than %u", 1065f024827SGleb Smirnoff CARP_MAXVHID); 1075f024827SGleb Smirnoff 1085f024827SGleb Smirnoff switch (afp->af_af) { 1095f024827SGleb Smirnoff #ifdef INET 1105f024827SGleb Smirnoff case AF_INET: 1115f024827SGleb Smirnoff { 1125f024827SGleb Smirnoff struct in_aliasreq *ifra; 1135f024827SGleb Smirnoff 1145f024827SGleb Smirnoff ifra = (struct in_aliasreq *)afp->af_addreq; 1155f024827SGleb Smirnoff ifra->ifra_vhid = carpr_vhid; 1165f024827SGleb Smirnoff break; 1175f024827SGleb Smirnoff } 1185f024827SGleb Smirnoff #endif 1195f024827SGleb Smirnoff #ifdef INET6 1205f024827SGleb Smirnoff case AF_INET6: 1215f024827SGleb Smirnoff { 1225f024827SGleb Smirnoff struct in6_aliasreq *ifra; 1235f024827SGleb Smirnoff 1245f024827SGleb Smirnoff ifra = (struct in6_aliasreq *)afp->af_addreq; 1255f024827SGleb Smirnoff ifra->ifra_vhid = carpr_vhid; 1265f024827SGleb Smirnoff break; 1275f024827SGleb Smirnoff } 1285f024827SGleb Smirnoff #endif 1295f024827SGleb Smirnoff default: 1305f024827SGleb Smirnoff errx(1, "%s doesn't support carp(4)", afp->af_name); 1315f024827SGleb Smirnoff } 1325f024827SGleb Smirnoff 1335f024827SGleb Smirnoff callback_register(setcarp_callback, NULL); 1345f024827SGleb Smirnoff } 1355f024827SGleb Smirnoff 1365f024827SGleb Smirnoff static void 1375f024827SGleb Smirnoff setcarp_callback(int s, void *arg __unused) 1385f024827SGleb Smirnoff { 1395f024827SGleb Smirnoff struct carpreq carpr; 1405f024827SGleb Smirnoff 1415f024827SGleb Smirnoff bzero(&carpr, sizeof(struct carpreq)); 1425f024827SGleb Smirnoff carpr.carpr_vhid = carpr_vhid; 1435f024827SGleb Smirnoff carpr.carpr_count = 1; 1445f024827SGleb Smirnoff ifr.ifr_data = (caddr_t)&carpr; 1455f024827SGleb Smirnoff 1465f024827SGleb Smirnoff if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1 && errno != ENOENT) 1475f024827SGleb Smirnoff err(1, "SIOCGVH"); 1485f024827SGleb Smirnoff 1495f024827SGleb Smirnoff if (carpr_key != NULL) 1505f024827SGleb Smirnoff /* XXX Should hash the password into the key here? */ 1515f024827SGleb Smirnoff strlcpy(carpr.carpr_key, carpr_key, CARP_KEY_LEN); 1525f024827SGleb Smirnoff if (carpr_advskew > -1) 1535f024827SGleb Smirnoff carpr.carpr_advskew = carpr_advskew; 1545f024827SGleb Smirnoff if (carpr_advbase > -1) 1555f024827SGleb Smirnoff carpr.carpr_advbase = carpr_advbase; 1565f024827SGleb Smirnoff if (carpr_state > -1) 1575f024827SGleb Smirnoff carpr.carpr_state = carpr_state; 1585f024827SGleb Smirnoff 1595f024827SGleb Smirnoff if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 1605f024827SGleb Smirnoff err(1, "SIOCSVH"); 1615f024827SGleb Smirnoff } 1625f024827SGleb Smirnoff 1635f024827SGleb Smirnoff static void 1645f024827SGleb Smirnoff setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) 1655f024827SGleb Smirnoff { 1665f024827SGleb Smirnoff 1675f024827SGleb Smirnoff if (carpr_vhid == -1) 1685f024827SGleb Smirnoff errx(1, "passwd requires vhid"); 1695f024827SGleb Smirnoff 1705f024827SGleb Smirnoff carpr_key = val; 1715f024827SGleb Smirnoff } 1725f024827SGleb Smirnoff 1735f024827SGleb Smirnoff static void 1745f024827SGleb Smirnoff setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) 1755f024827SGleb Smirnoff { 1765f024827SGleb Smirnoff 1775f024827SGleb Smirnoff if (carpr_vhid == -1) 1785f024827SGleb Smirnoff errx(1, "advskew requires vhid"); 1795f024827SGleb Smirnoff 1805f024827SGleb Smirnoff carpr_advskew = atoi(val); 1815f024827SGleb Smirnoff } 1825f024827SGleb Smirnoff 1835f024827SGleb Smirnoff static void 1845f024827SGleb Smirnoff setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) 1855f024827SGleb Smirnoff { 1865f024827SGleb Smirnoff 1875f024827SGleb Smirnoff if (carpr_vhid == -1) 1885f024827SGleb Smirnoff errx(1, "advbase requires vhid"); 1895f024827SGleb Smirnoff 1905f024827SGleb Smirnoff carpr_advbase = atoi(val); 1915f024827SGleb Smirnoff } 1925f024827SGleb Smirnoff 1935f024827SGleb Smirnoff static void 1945f024827SGleb Smirnoff setcarp_state(const char *val, int d, int s, const struct afswtch *afp) 1955f024827SGleb Smirnoff { 1965f024827SGleb Smirnoff int i; 1975f024827SGleb Smirnoff 1985f024827SGleb Smirnoff if (carpr_vhid == -1) 1995f024827SGleb Smirnoff errx(1, "state requires vhid"); 2005f024827SGleb Smirnoff 2015f024827SGleb Smirnoff for (i = 0; i <= CARP_MAXSTATE; i++) 2025f024827SGleb Smirnoff if (strcasecmp(carp_states[i], val) == 0) { 2035f024827SGleb Smirnoff carpr_state = i; 2045f024827SGleb Smirnoff return; 2055f024827SGleb Smirnoff } 2065f024827SGleb Smirnoff 2075f024827SGleb Smirnoff errx(1, "unknown state"); 2085f024827SGleb Smirnoff } 2095f024827SGleb Smirnoff 2105f024827SGleb Smirnoff static struct cmd carp_cmds[] = { 2115f024827SGleb Smirnoff DEF_CMD_ARG("advbase", setcarp_advbase), 2125f024827SGleb Smirnoff DEF_CMD_ARG("advskew", setcarp_advskew), 2135f024827SGleb Smirnoff DEF_CMD_ARG("pass", setcarp_passwd), 2145f024827SGleb Smirnoff DEF_CMD_ARG("vhid", setcarp_vhid), 2155f024827SGleb Smirnoff DEF_CMD_ARG("state", setcarp_state), 2165f024827SGleb Smirnoff }; 2175f024827SGleb Smirnoff static struct afswtch af_carp = { 2185f024827SGleb Smirnoff .af_name = "af_carp", 2195f024827SGleb Smirnoff .af_af = AF_UNSPEC, 2205f024827SGleb Smirnoff .af_other_status = carp_status, 2215f024827SGleb Smirnoff }; 2225f024827SGleb Smirnoff 2235f024827SGleb Smirnoff static __constructor void 2245f024827SGleb Smirnoff carp_ctor(void) 2255f024827SGleb Smirnoff { 2265f024827SGleb Smirnoff int i; 2275f024827SGleb Smirnoff 228abd71050SEnji Cooper for (i = 0; i < nitems(carp_cmds); i++) 2295f024827SGleb Smirnoff cmd_register(&carp_cmds[i]); 2305f024827SGleb Smirnoff af_register(&af_carp); 2315f024827SGleb Smirnoff } 232