1 /* $NetBSD: af_inet.c,v 1.1 2005/03/20 02:43:50 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __RCSID("$NetBSD: af_inet.c,v 1.1 2005/03/20 02:43:50 thorpej Exp $"); 35 #endif /* not lint */ 36 37 #include <sys/param.h> 38 #include <sys/ioctl.h> 39 #include <sys/socket.h> 40 41 #include <net/if.h> 42 #include <netinet/in.h> 43 #include <netinet/in_var.h> 44 45 #include <arpa/inet.h> 46 47 #include <err.h> 48 #include <errno.h> 49 #include <ifaddrs.h> 50 #include <netdb.h> 51 #include <string.h> 52 #include <stdlib.h> 53 #include <stdio.h> 54 55 #include "extern.h" 56 #include "af_inet.h" 57 58 struct in_aliasreq in_addreq; 59 60 int setipdst; 61 62 void 63 setifipdst(const char *addr, int d) 64 { 65 66 in_getaddr(addr, DSTADDR); 67 setipdst++; 68 clearaddr = 0; 69 newaddr = 0; 70 } 71 72 void 73 in_alias(struct ifreq *creq) 74 { 75 struct sockaddr_in *iasin; 76 int alias; 77 78 if (lflag) 79 return; 80 81 alias = 1; 82 83 /* Get the non-alias address for this interface. */ 84 getsock(AF_INET); 85 if (s < 0) { 86 if (errno == EPROTONOSUPPORT) 87 return; 88 err(EXIT_FAILURE, "socket"); 89 } 90 (void) memset(&ifr, 0, sizeof(ifr)); 91 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 92 if (ioctl(s, SIOCGIFADDR, &ifr) == -1) { 93 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 94 return; 95 } else 96 warn("SIOCGIFADDR"); 97 } 98 /* If creq and ifr are the same address, this is not an alias. */ 99 if (memcmp(&ifr.ifr_addr, &creq->ifr_addr, 100 sizeof(creq->ifr_addr)) == 0) 101 alias = 0; 102 (void) memset(&in_addreq, 0, sizeof(in_addreq)); 103 (void) strncpy(in_addreq.ifra_name, name, sizeof(in_addreq.ifra_name)); 104 memcpy(&in_addreq.ifra_addr, &creq->ifr_addr, 105 sizeof(in_addreq.ifra_addr)); 106 if (ioctl(s, SIOCGIFALIAS, &in_addreq) == -1) { 107 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 108 return; 109 } else 110 warn("SIOCGIFALIAS"); 111 } 112 113 iasin = &in_addreq.ifra_addr; 114 printf("\tinet %s%s", alias ? "alias " : "", inet_ntoa(iasin->sin_addr)); 115 116 if (flags & IFF_POINTOPOINT) { 117 iasin = &in_addreq.ifra_dstaddr; 118 printf(" -> %s", inet_ntoa(iasin->sin_addr)); 119 } 120 121 iasin = &in_addreq.ifra_mask; 122 printf(" netmask 0x%x", ntohl(iasin->sin_addr.s_addr)); 123 124 if (flags & IFF_BROADCAST) { 125 iasin = &in_addreq.ifra_broadaddr; 126 printf(" broadcast %s", inet_ntoa(iasin->sin_addr)); 127 } 128 printf("\n"); 129 } 130 131 void 132 in_status(int force) 133 { 134 struct ifaddrs *ifap, *ifa; 135 struct ifreq isifr; 136 137 if (getifaddrs(&ifap) != 0) 138 err(EXIT_FAILURE, "getifaddrs"); 139 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 140 if (strcmp(name, ifa->ifa_name) != 0) 141 continue; 142 if (ifa->ifa_addr->sa_family != AF_INET) 143 continue; 144 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len) 145 continue; 146 147 memset(&isifr, 0, sizeof(isifr)); 148 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name)); 149 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 150 in_alias(&isifr); 151 } 152 freeifaddrs(ifap); 153 } 154 155 #define SIN(x) ((struct sockaddr_in *) &(x)) 156 struct sockaddr_in *sintab[] = { 157 SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr), 158 SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)}; 159 160 void 161 in_getaddr(const char *str, int which) 162 { 163 struct sockaddr_in *gasin = sintab[which]; 164 struct hostent *hp; 165 struct netent *np; 166 167 gasin->sin_len = sizeof(*gasin); 168 if (which != MASK) 169 gasin->sin_family = AF_INET; 170 171 if (which == ADDR) { 172 char *p = NULL; 173 if ((p = strrchr(str, '/')) != NULL) { 174 *p = '\0'; 175 in_getprefix(p + 1, MASK); 176 } 177 } 178 179 if (inet_aton(str, &gasin->sin_addr) == 0) { 180 if ((hp = gethostbyname(str)) != NULL) 181 (void) memcpy(&gasin->sin_addr, hp->h_addr, hp->h_length); 182 else if ((np = getnetbyname(str)) != NULL) 183 gasin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 184 else 185 errx(EXIT_FAILURE, "%s: bad value", str); 186 } 187 } 188 189 void 190 in_getprefix(const char *plen, int which) 191 { 192 struct sockaddr_in *igsin = sintab[which]; 193 u_char *cp; 194 int len = strtol(plen, (char **)NULL, 10); 195 196 if ((len < 0) || (len > 32)) 197 errx(EXIT_FAILURE, "%s: bad value", plen); 198 igsin->sin_len = sizeof(*igsin); 199 if (which != MASK) 200 igsin->sin_family = AF_INET; 201 if ((len == 0) || (len == 32)) { 202 memset(&igsin->sin_addr, 0xff, sizeof(struct in_addr)); 203 return; 204 } 205 memset((void *)&igsin->sin_addr, 0x00, sizeof(igsin->sin_addr)); 206 for (cp = (u_char *)&igsin->sin_addr; len > 7; len -= 8) 207 *cp++ = 0xff; 208 if (len) 209 *cp = 0xff << (8 - len); 210 } 211