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 36 #include <stdlib.h> 37 #include <unistd.h> 38 39 #include <net/ethernet.h> 40 #include <net/if.h> 41 #include <netinet/in.h> 42 #include <netinet/ip_carp.h> 43 #include <net/route.h> 44 45 #include <arpa/inet.h> 46 47 #include <ctype.h> 48 #include <stdio.h> 49 #include <string.h> 50 #include <stdlib.h> 51 #include <unistd.h> 52 #include <err.h> 53 #include <errno.h> 54 55 #include "ifconfig.h" 56 57 static const char *carp_states[] = { CARP_STATES }; 58 59 void carp_status(int s); 60 void setcarp_advbase(const char *,int, int, const struct afswtch *rafp); 61 void setcarp_advskew(const char *, int, int, const struct afswtch *rafp); 62 void setcarp_passwd(const char *, int, int, const struct afswtch *rafp); 63 void setcarp_vhid(const char *, int, int, const struct afswtch *rafp); 64 65 void 66 carp_status(int s) 67 { 68 const char *state; 69 struct carpreq carpr; 70 struct ifdrv ifd; 71 char devname[IFNAMSIZ]; 72 73 memset((char *)&carpr, 0, sizeof(struct carpreq)); 74 ifr.ifr_data = (caddr_t)&carpr; 75 76 if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 77 return; 78 79 if (carpr.carpr_vhid > 0) { 80 if (carpr.carpr_state > CARP_MAXSTATE) 81 state = "<UNKNOWN>"; 82 else 83 state = carp_states[carpr.carpr_state]; 84 85 printf("\tcarp: %s vhid %d advbase %d advskew %d\n", 86 state, carpr.carpr_vhid, carpr.carpr_advbase, 87 carpr.carpr_advskew); 88 } 89 90 memset(&ifd, 0, sizeof(ifd)); 91 strncpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); 92 ifd.ifd_cmd = CARPGDEVNAME; 93 ifd.ifd_len = sizeof(devname); 94 ifd.ifd_data = devname; 95 if (ioctl(s, SIOCGDRVSPEC, &ifd) < 0) 96 strlcpy(devname, "none", sizeof(devname)); 97 if (devname[0] != '\0') 98 printf("\tcarpdev: %s\n", devname); 99 } 100 101 void 102 setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp) 103 { 104 struct carpreq carpr; 105 106 memset((char *)&carpr, 0, sizeof(struct carpreq)); 107 ifr.ifr_data = (caddr_t)&carpr; 108 109 if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 110 err(1, "SIOCGVH"); 111 112 /* XXX Should hash the password into the key here, perhaps? */ 113 strlcpy(carpr.carpr_key, val, CARP_KEY_LEN); 114 115 if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 116 err(1, "SIOCSVH"); 117 } 118 119 void 120 setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp) 121 { 122 int vhid; 123 struct carpreq carpr; 124 125 vhid = atoi(val); 126 127 if (vhid <= 0) 128 errx(1, "vhid must be greater than 0"); 129 130 memset((char *)&carpr, 0, sizeof(struct carpreq)); 131 ifr.ifr_data = (caddr_t)&carpr; 132 133 if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 134 err(1, "SIOCGVH"); 135 136 carpr.carpr_vhid = vhid; 137 138 if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 139 err(1, "SIOCSVH"); 140 } 141 142 void 143 setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp) 144 { 145 int advskew; 146 struct carpreq carpr; 147 148 advskew = atoi(val); 149 150 memset((char *)&carpr, 0, sizeof(struct carpreq)); 151 ifr.ifr_data = (caddr_t)&carpr; 152 153 if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 154 err(1, "SIOCGVH"); 155 156 carpr.carpr_advskew = advskew; 157 158 if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 159 err(1, "SIOCSVH"); 160 } 161 162 void 163 setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp) 164 { 165 int advbase; 166 struct carpreq carpr; 167 168 advbase = atoi(val); 169 170 memset((char *)&carpr, 0, sizeof(struct carpreq)); 171 ifr.ifr_data = (caddr_t)&carpr; 172 173 if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) 174 err(1, "SIOCGVH"); 175 176 carpr.carpr_advbase = advbase; 177 178 if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1) 179 err(1, "SIOCSVH"); 180 } 181 182 static void 183 getcarp_vhaddr(const char *val, int d, int s, const struct afswtch *afp) 184 { 185 #define VHADDR_PFMT "%-15s %-15s %s\n" 186 187 struct ifdrv ifd; 188 struct ifcarpvhaddr *carpa; 189 int count, i; 190 191 memset(&ifd, 0, sizeof(ifd)); 192 strncpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name)); 193 ifd.ifd_cmd = CARPGVHADDR; 194 if (ioctl(s, SIOCGDRVSPEC, &ifd) < 0) 195 return; 196 if (ifd.ifd_len != 0) { 197 carpa = malloc(ifd.ifd_len); 198 if (carpa == NULL) 199 return; 200 201 ifd.ifd_cmd = CARPGVHADDR; 202 ifd.ifd_data = carpa; 203 if (ioctl(s, SIOCGDRVSPEC, &ifd) < 0) { 204 free(carpa); 205 return; 206 } 207 } else { 208 carpa = NULL; 209 } 210 count = ifd.ifd_len / sizeof(*carpa); 211 if (count != 0) 212 printf(VHADDR_PFMT, "virtual addr", "backing addr", "flags"); 213 for (i = 0; i < count; ++i) { 214 char flags[16]; 215 char baddr[INET_ADDRSTRLEN]; 216 int a = 0; 217 218 memset(flags, 0, sizeof(flags)); 219 flags[a] = '*'; 220 if (carpa[i].carpa_flags & CARP_VHAF_OWNER) 221 flags[a++] = 'O'; 222 223 memset(baddr, 0, sizeof(baddr)); 224 baddr[0] = '*'; 225 if (carpa[i].carpa_baddr.sin_addr.s_addr != INADDR_ANY) { 226 inet_ntop(AF_INET, &carpa[i].carpa_baddr.sin_addr, 227 baddr, sizeof(baddr)); 228 } 229 230 printf(VHADDR_PFMT, inet_ntoa(carpa[i].carpa_addr.sin_addr), 231 baddr, flags); 232 } 233 if (carpa != NULL) 234 free(carpa); 235 236 #undef VHADDR_PFMT 237 } 238 239 static struct cmd carp_cmds[] = { 240 DEF_CMD_ARG("advbase", setcarp_advbase), 241 DEF_CMD_ARG("advskew", setcarp_advskew), 242 DEF_CMD_ARG("pass", setcarp_passwd), 243 DEF_CMD_ARG("vhid", setcarp_vhid), 244 DEF_CMD("vhaddr", 1, getcarp_vhaddr) 245 }; 246 static struct afswtch af_carp = { 247 .af_name = "af_carp", 248 .af_af = AF_UNSPEC, 249 .af_other_status = carp_status, 250 }; 251 252 static __constructor(101) void 253 carp_ctor(void) 254 { 255 #define N(a) (sizeof(a) / sizeof(a[0])) 256 int i; 257 258 for (i = 0; i < N(carp_cmds); i++) 259 cmd_register(&carp_cmds[i]); 260 af_register(&af_carp); 261 #undef N 262 } 263