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