1 /* 2 * Copyright (c) 2002 Michael Shalayeff. All rights reserved. 3 * Copyright (c) 2003 Ryan McBride. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 * THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 /* 27 * $FreeBSD: src/sbin/ifconfig/ifcarp.c,v 1.2 2005/02/22 14:07:47 glebius Exp $ 28 * $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/ioctl.h> 33 #include <sys/socket.h> 34 #include <sys/sockio.h> 35 #include <net/if.h> 36 #include <net/route.h> 37 #include <net/ethernet.h> 38 #include <netinet/in.h> 39 #include <netinet/ip_carp.h> 40 #include <arpa/inet.h> 41 42 #include <ctype.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 #include <err.h> 48 #include <errno.h> 49 50 #include "ifconfig.h" 51 52 static const char *carp_states[] = { CARP_STATES }; 53 54 static void 55 carp_status(int s) 56 { 57 struct carpreq carpr; 58 struct ifreq ifr; 59 struct ifdrv ifd; 60 const char *state; 61 char devname[IFNAMSIZ]; 62 63 memset(&ifr, 0, sizeof(ifr)); 64 memset(&carpr, 0, sizeof(carpr)); 65 66 strlcpy(ifr.ifr_name, IfName, sizeof(ifr.ifr_name)); 67 ifr.ifr_data = &carpr; 68 69 if (ioctl(s, SIOCGVH, &ifr) == -1) 70 return; 71 72 if (carpr.carpr_vhid > 0) { 73 if (carpr.carpr_state > CARP_MAXSTATE) 74 state = "<UNKNOWN>"; 75 else 76 state = carp_states[carpr.carpr_state]; 77 78 printf("\tcarp: %s vhid %d advbase %d advskew %d\n", 79 state, carpr.carpr_vhid, carpr.carpr_advbase, 80 carpr.carpr_advskew); 81 } 82 83 memset(&ifd, 0, sizeof(ifd)); 84 strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); 85 ifd.ifd_cmd = CARPGDEVNAME; 86 ifd.ifd_len = sizeof(devname); 87 ifd.ifd_data = devname; 88 if (ioctl(s, SIOCGDRVSPEC, &ifd) < 0) 89 strlcpy(devname, "none", sizeof(devname)); 90 if (devname[0] != '\0') 91 printf("\tcarpdev: %s\n", devname); 92 } 93 94 static void 95 setcarp_passwd(const char *val, int d __unused, int s, 96 const struct afswtch *afp __unused) 97 { 98 struct carpreq carpr; 99 struct ifreq ifr; 100 101 memset(&ifr, 0, sizeof(ifr)); 102 memset(&carpr, 0, sizeof(carpr)); 103 104 strlcpy(ifr.ifr_name, IfName, sizeof(ifr.ifr_name)); 105 ifr.ifr_data = &carpr; 106 107 if (ioctl(s, SIOCGVH, &ifr) == -1) 108 err(1, "SIOCGVH"); 109 110 /* XXX Should hash the password into the key here, perhaps? */ 111 strlcpy(carpr.carpr_key, val, CARP_KEY_LEN); 112 113 if (ioctl(s, SIOCSVH, &ifr) == -1) 114 err(1, "SIOCSVH"); 115 } 116 117 static void 118 setcarp_vhid(const char *val, int d __unused, int s, 119 const struct afswtch *afp __unused) 120 { 121 struct carpreq carpr; 122 struct ifreq ifr; 123 int vhid; 124 125 vhid = atoi(val); 126 if (vhid <= 0) 127 errx(1, "vhid must be greater than 0"); 128 129 memset(&ifr, 0, sizeof(ifr)); 130 memset(&carpr, 0, sizeof(carpr)); 131 132 strlcpy(ifr.ifr_name, IfName, sizeof(ifr.ifr_name)); 133 ifr.ifr_data = &carpr; 134 135 if (ioctl(s, SIOCGVH, &ifr) == -1) 136 err(1, "SIOCGVH"); 137 138 carpr.carpr_vhid = vhid; 139 140 if (ioctl(s, SIOCSVH, &ifr) == -1) 141 err(1, "SIOCSVH"); 142 } 143 144 static void 145 setcarp_advskew(const char *val, int d __unused, int s, 146 const struct afswtch *afp __unused) 147 { 148 struct carpreq carpr; 149 struct ifreq ifr; 150 int advskew; 151 152 advskew = atoi(val); 153 154 memset(&ifr, 0, sizeof(ifr)); 155 memset(&carpr, 0, sizeof(carpr)); 156 157 strlcpy(ifr.ifr_name, IfName, sizeof(ifr.ifr_name)); 158 ifr.ifr_data = &carpr; 159 160 if (ioctl(s, SIOCGVH, &ifr) == -1) 161 err(1, "SIOCGVH"); 162 163 carpr.carpr_advskew = advskew; 164 165 if (ioctl(s, SIOCSVH, &ifr) == -1) 166 err(1, "SIOCSVH"); 167 } 168 169 static void 170 setcarp_advbase(const char *val, int d __unused, int s, 171 const struct afswtch *afp __unused) 172 { 173 struct carpreq carpr; 174 struct ifreq ifr; 175 int advbase; 176 177 advbase = atoi(val); 178 179 memset(&ifr, 0, sizeof(ifr)); 180 memset(&carpr, 0, sizeof(carpr)); 181 182 strlcpy(ifr.ifr_name, IfName, sizeof(ifr.ifr_name)); 183 ifr.ifr_data = &carpr; 184 185 if (ioctl(s, SIOCGVH, &ifr) == -1) 186 err(1, "SIOCGVH"); 187 188 carpr.carpr_advbase = advbase; 189 190 if (ioctl(s, SIOCSVH, &ifr) == -1) 191 err(1, "SIOCSVH"); 192 } 193 194 static void 195 getcarp_vhaddr(const char *val __unused, int d __unused, int s, 196 const struct afswtch *afp __unused) 197 { 198 #define VHADDR_PFMT "%-15s %-15s %s\n" 199 200 struct ifdrv ifd; 201 struct ifcarpvhaddr *carpa; 202 int count, i; 203 204 memset(&ifd, 0, sizeof(ifd)); 205 strlcpy(ifd.ifd_name, IfName, sizeof(ifd.ifd_name)); 206 ifd.ifd_cmd = CARPGVHADDR; 207 if (ioctl(s, SIOCGDRVSPEC, &ifd) < 0) 208 return; 209 if (ifd.ifd_len != 0) { 210 carpa = malloc(ifd.ifd_len); 211 if (carpa == NULL) 212 return; 213 214 ifd.ifd_cmd = CARPGVHADDR; 215 ifd.ifd_data = carpa; 216 if (ioctl(s, SIOCGDRVSPEC, &ifd) < 0) { 217 free(carpa); 218 return; 219 } 220 } else { 221 carpa = NULL; 222 } 223 count = ifd.ifd_len / sizeof(*carpa); 224 if (count != 0) 225 printf(VHADDR_PFMT, "virtual addr", "backing addr", "flags"); 226 for (i = 0; i < count; ++i) { 227 char flags[16]; 228 char baddr[INET_ADDRSTRLEN]; 229 int a = 0; 230 231 memset(flags, 0, sizeof(flags)); 232 flags[a] = '*'; 233 if (carpa[i].carpa_flags & CARP_VHAF_OWNER) 234 flags[a++] = 'O'; 235 236 memset(baddr, 0, sizeof(baddr)); 237 baddr[0] = '*'; 238 if (carpa[i].carpa_baddr.sin_addr.s_addr != INADDR_ANY) { 239 inet_ntop(AF_INET, &carpa[i].carpa_baddr.sin_addr, 240 baddr, sizeof(baddr)); 241 } 242 243 printf(VHADDR_PFMT, inet_ntoa(carpa[i].carpa_addr.sin_addr), 244 baddr, flags); 245 } 246 if (carpa != NULL) 247 free(carpa); 248 249 #undef VHADDR_PFMT 250 } 251 252 static struct cmd carp_cmds[] = { 253 DEF_CMD_ARG("advbase", setcarp_advbase), 254 DEF_CMD_ARG("advskew", setcarp_advskew), 255 DEF_CMD_ARG("pass", setcarp_passwd), 256 DEF_CMD_ARG("vhid", setcarp_vhid), 257 DEF_CMD("vhaddr", 1, getcarp_vhaddr) 258 }; 259 static struct afswtch af_carp = { 260 .af_name = "af_carp", 261 .af_af = AF_UNSPEC, 262 .af_other_status = carp_status, 263 }; 264 265 __constructor(131) 266 static void 267 carp_ctor(void) 268 { 269 size_t i; 270 271 for (i = 0; i < nitems(carp_cmds); i++) 272 cmd_register(&carp_cmds[i]); 273 274 af_register(&af_carp); 275 } 276