1/* 2 * Copyright (c) 2009-2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * Copyright (c) 1983, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 4. Neither the name of the University nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58#ifndef lint 59static const char rcsid[] = 60 "$FreeBSD: src/sbin/ifconfig/af_inet.c,v 1.3.6.1 2008/11/25 02:59:29 kensmith Exp $"; 61#endif /* not lint */ 62 63#include <sys/types.h> 64#include <sys/ioctl.h> 65#include <sys/socket.h> 66#include <net/if.h> 67 68#include <err.h> 69#include <stdio.h> 70#include <stdlib.h> 71#include <string.h> 72#include <unistd.h> 73#include <ifaddrs.h> 74 75#include <netinet/in.h> 76#include <net/if_var.h> /* for struct ifaddr */ 77#include <netinet/in_var.h> 78#include <arpa/inet.h> 79#include <netdb.h> 80 81#include "ifconfig.h" 82 83static struct ifaliasreq in_addreq; 84static struct ifreq in_ridreq; 85 86static void 87in_status(int s __unused, const struct ifaddrs *ifa) 88{ 89 struct sockaddr_in *sin, null_sin; 90 91 memset(&null_sin, 0, sizeof(null_sin)); 92 93 sin = (struct sockaddr_in *)ifa->ifa_addr; 94 if (sin == NULL) 95 return; 96 97 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 98 99 if (ifa->ifa_flags & IFF_POINTOPOINT) { 100 sin = (struct sockaddr_in *)ifa->ifa_dstaddr; 101 if (sin == NULL) 102 sin = &null_sin; 103 printf("--> %s ", inet_ntoa(sin->sin_addr)); 104 } 105 106 sin = (struct sockaddr_in *)ifa->ifa_netmask; 107 if (sin == NULL) 108 sin = &null_sin; 109 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 110 111 if (ifa->ifa_flags & IFF_BROADCAST) { 112 sin = (struct sockaddr_in *)ifa->ifa_broadaddr; 113 if (sin != NULL && sin->sin_addr.s_addr != 0) 114 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 115 } 116 putchar('\n'); 117} 118 119#define SIN(x) ((struct sockaddr_in *) &(x)) 120static struct sockaddr_in *sintab[] = { 121 SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr), 122 SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr) 123}; 124 125static void 126in_getaddr(const char *s, int which) 127{ 128#ifndef MIN 129#define MIN(a,b) ((a)<(b)?(a):(b)) 130#endif /* MIN */ 131 struct sockaddr_in *sin = sintab[which]; 132 struct hostent *hp; 133 struct netent *np; 134 135 sin->sin_len = sizeof(*sin); 136 if (which != MASK) 137 sin->sin_family = AF_INET; 138 139 if (which == ADDR) { 140 char *p = NULL; 141 142 if((p = strrchr(s, '/')) != NULL) { 143 /* address is `name/masklen' */ 144 int masklen; 145 int ret; 146 struct sockaddr_in *min = sintab[MASK]; 147 *p = '\0'; 148 ret = sscanf(p+1, "%u", &masklen); 149 if(ret != 1 || (masklen < 0 || masklen > 32)) { 150 *p = '/'; 151 errx(1, "%s: bad value", s); 152 } 153 min->sin_len = sizeof(*min); 154 min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) & 155 0xffffffff); 156 } 157 } 158 159 if (inet_aton(s, &sin->sin_addr)) 160 return; 161 if ((hp = gethostbyname(s)) != 0) 162 bcopy(hp->h_addr, (char *)&sin->sin_addr, 163 MIN(hp->h_length, sizeof(sin->sin_addr))); 164 else if ((np = getnetbyname(s)) != 0) 165 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 166 else 167 errx(1, "%s: bad value", s); 168#undef MIN 169} 170 171static void 172in_status_tunnel(int s) 173{ 174 char src[NI_MAXHOST]; 175 char dst[NI_MAXHOST]; 176 struct ifreq ifr; 177 const struct sockaddr *sa = (const struct sockaddr *) &ifr.ifr_addr; 178 179 memset(&ifr, 0, sizeof(ifr)); 180 strncpy(ifr.ifr_name, name, IFNAMSIZ); 181 182 if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0) 183 return; 184 if (sa->sa_family != AF_INET) 185 return; 186 if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0) 187 src[0] = '\0'; 188 189 if (ioctl(s, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0) 190 return; 191 if (sa->sa_family != AF_INET) 192 return; 193 if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0) 194 dst[0] = '\0'; 195 196 printf("\ttunnel inet %s --> %s\n", src, dst); 197} 198 199static void 200in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres) 201{ 202 struct ifaliasreq addreq; 203 204 memset(&addreq, 0, sizeof(addreq)); 205 strncpy(addreq.ifra_name, name, IFNAMSIZ); 206 memcpy(&addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); 207 memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); 208 209 if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0) 210 warn("SIOCSIFPHYADDR"); 211} 212 213static void 214in_set_router(int s, int enable) 215{ 216 struct ifreq ifr; 217 218 bzero(&ifr, sizeof (ifr)); 219 strncpy(ifr.ifr_name, name, IFNAMSIZ); 220 ifr.ifr_intval = enable; 221 222 if (ioctl(s, SIOCSETROUTERMODE, &ifr) < 0) 223 warn("SIOCSETROUTERMODE"); 224} 225 226static struct afswtch af_inet = { 227 .af_name = "inet", 228 .af_af = AF_INET, 229 .af_status = in_status, 230 .af_getaddr = in_getaddr, 231 .af_status_tunnel = in_status_tunnel, 232 .af_settunnel = in_set_tunnel, 233 .af_setrouter = in_set_router, 234 .af_difaddr = SIOCDIFADDR, 235 .af_aifaddr = SIOCAIFADDR, 236 .af_ridreq = &in_ridreq, 237 .af_addreq = &in_addreq, 238}; 239 240static __constructor void 241inet_ctor(void) 242{ 243 af_register(&af_inet); 244} 245