af_inet.c revision 191121
133965Sjdp/* 233965Sjdp * Copyright (c) 1983, 1993 333965Sjdp * The Regents of the University of California. All rights reserved. 460484Sobrien * 533965Sjdp * Redistribution and use in source and binary forms, with or without 633965Sjdp * modification, are permitted provided that the following conditions 733965Sjdp * are met: 833965Sjdp * 1. Redistributions of source code must retain the above copyright 933965Sjdp * notice, this list of conditions and the following disclaimer. 1033965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1133965Sjdp * notice, this list of conditions and the following disclaimer in the 1233965Sjdp * documentation and/or other materials provided with the distribution. 1333965Sjdp * 4. Neither the name of the University nor the names of its contributors 1433965Sjdp * may be used to endorse or promote products derived from this software 1533965Sjdp * without specific prior written permission. 1633965Sjdp * 1733965Sjdp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1833965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1933965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2033965Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2133965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2233965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2333965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2433965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2533965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2633965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2733965Sjdp * SUCH DAMAGE. 2833965Sjdp */ 2933965Sjdp 3033965Sjdp#ifndef lint 3133965Sjdpstatic const char rcsid[] = 3260484Sobrien "$FreeBSD: head/sbin/ifconfig/af_inet.c 191121 2009-04-15 20:53:34Z brooks $"; 3333965Sjdp#endif /* not lint */ 3433965Sjdp 3533965Sjdp#include <sys/types.h> 3633965Sjdp#include <sys/ioctl.h> 3733965Sjdp#include <sys/socket.h> 3833965Sjdp#include <net/if.h> 3933965Sjdp 4033965Sjdp#include <err.h> 4133965Sjdp#include <stdio.h> 4233965Sjdp#include <stdlib.h> 4333965Sjdp#include <string.h> 4433965Sjdp#include <unistd.h> 4533965Sjdp#include <ifaddrs.h> 4633965Sjdp 4733965Sjdp#include <netinet/in.h> 4833965Sjdp#include <net/if_var.h> /* for struct ifaddr */ 4933965Sjdp#include <netinet/in_var.h> 5033965Sjdp#include <arpa/inet.h> 5133965Sjdp#include <netdb.h> 5233965Sjdp 5333965Sjdp#include "ifconfig.h" 5433965Sjdp 5533965Sjdpstatic struct in_aliasreq in_addreq; 5633965Sjdpstatic struct ifreq in_ridreq; 5733965Sjdp 5833965Sjdpstatic void 5933965Sjdpin_status(int s __unused, const struct ifaddrs *ifa) 6033965Sjdp{ 6133965Sjdp struct sockaddr_in *sin, null_sin; 6233965Sjdp 6333965Sjdp memset(&null_sin, 0, sizeof(null_sin)); 6433965Sjdp 6533965Sjdp sin = (struct sockaddr_in *)ifa->ifa_addr; 6633965Sjdp if (sin == NULL) 6733965Sjdp return; 6833965Sjdp 6933965Sjdp printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 7033965Sjdp 7133965Sjdp if (ifa->ifa_flags & IFF_POINTOPOINT) { 7233965Sjdp sin = (struct sockaddr_in *)ifa->ifa_dstaddr; 7333965Sjdp if (sin == NULL) 7433965Sjdp sin = &null_sin; 7533965Sjdp printf("--> %s ", inet_ntoa(sin->sin_addr)); 7633965Sjdp } 7733965Sjdp 7833965Sjdp sin = (struct sockaddr_in *)ifa->ifa_netmask; 7933965Sjdp if (sin == NULL) 8033965Sjdp sin = &null_sin; 8133965Sjdp printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 8233965Sjdp 8333965Sjdp if (ifa->ifa_flags & IFF_BROADCAST) { 8433965Sjdp sin = (struct sockaddr_in *)ifa->ifa_broadaddr; 8533965Sjdp if (sin != NULL && sin->sin_addr.s_addr != 0) 8633965Sjdp printf("broadcast %s", inet_ntoa(sin->sin_addr)); 8733965Sjdp } 8833965Sjdp putchar('\n'); 8933965Sjdp} 9033965Sjdp 9133965Sjdp#define SIN(x) ((struct sockaddr_in *) &(x)) 9233965Sjdpstatic struct sockaddr_in *sintab[] = { 9333965Sjdp SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr), 9433965Sjdp SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr) 9533965Sjdp}; 9633965Sjdp 9733965Sjdpstatic void 9833965Sjdpin_getaddr(const char *s, int which) 9933965Sjdp{ 10033965Sjdp#define MIN(a,b) ((a)<(b)?(a):(b)) 10133965Sjdp struct sockaddr_in *sin = sintab[which]; 10233965Sjdp struct hostent *hp; 10333965Sjdp struct netent *np; 10433965Sjdp 10533965Sjdp sin->sin_len = sizeof(*sin); 10633965Sjdp if (which != MASK) 10733965Sjdp sin->sin_family = AF_INET; 10833965Sjdp 10933965Sjdp if (which == ADDR) { 11033965Sjdp char *p = NULL; 11133965Sjdp 11233965Sjdp if((p = strrchr(s, '/')) != NULL) { 11333965Sjdp /* address is `name/masklen' */ 11433965Sjdp int masklen; 11533965Sjdp int ret; 11633965Sjdp struct sockaddr_in *min = sintab[MASK]; 11733965Sjdp *p = '\0'; 11833965Sjdp ret = sscanf(p+1, "%u", &masklen); 11933965Sjdp if(ret != 1 || (masklen < 0 || masklen > 32)) { 12033965Sjdp *p = '/'; 12133965Sjdp errx(1, "%s: bad value", s); 12233965Sjdp } 12333965Sjdp min->sin_len = sizeof(*min); 12433965Sjdp min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) & 12533965Sjdp 0xffffffff); 12633965Sjdp } 12733965Sjdp } 12833965Sjdp 12933965Sjdp if (inet_aton(s, &sin->sin_addr)) 13033965Sjdp return; 13133965Sjdp if ((hp = gethostbyname(s)) != 0) 13233965Sjdp bcopy(hp->h_addr, (char *)&sin->sin_addr, 13333965Sjdp MIN(hp->h_length, sizeof(sin->sin_addr))); 13433965Sjdp else if ((np = getnetbyname(s)) != 0) 13533965Sjdp sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 13633965Sjdp else 13733965Sjdp errx(1, "%s: bad value", s); 13833965Sjdp#undef MIN 13933965Sjdp} 14033965Sjdp 14133965Sjdpstatic void 14233965Sjdpin_status_tunnel(int s) 14333965Sjdp{ 14433965Sjdp char src[NI_MAXHOST]; 14533965Sjdp char dst[NI_MAXHOST]; 14633965Sjdp struct ifreq ifr; 14733965Sjdp const struct sockaddr *sa = (const struct sockaddr *) &ifr.ifr_addr; 14833965Sjdp 14933965Sjdp memset(&ifr, 0, sizeof(ifr)); 15033965Sjdp strncpy(ifr.ifr_name, name, IFNAMSIZ); 15133965Sjdp 15233965Sjdp if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0) 15333965Sjdp return; 15433965Sjdp if (sa->sa_family != AF_INET) 15533965Sjdp return; 15633965Sjdp if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0) 15733965Sjdp src[0] = '\0'; 15833965Sjdp 15933965Sjdp if (ioctl(s, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0) 16033965Sjdp return; 16133965Sjdp if (sa->sa_family != AF_INET) 16233965Sjdp return; 16333965Sjdp if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0) 16433965Sjdp dst[0] = '\0'; 16533965Sjdp 16633965Sjdp printf("\ttunnel inet %s --> %s\n", src, dst); 16733965Sjdp} 16833965Sjdp 16933965Sjdpstatic void 17033965Sjdpin_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres) 17133965Sjdp{ 17233965Sjdp struct in_aliasreq addreq; 17333965Sjdp 17433965Sjdp memset(&addreq, 0, sizeof(addreq)); 17533965Sjdp strncpy(addreq.ifra_name, name, IFNAMSIZ); 17633965Sjdp memcpy(&addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len); 17733965Sjdp memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len); 17833965Sjdp 17933965Sjdp if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0) 18033965Sjdp warn("SIOCSIFPHYADDR"); 18133965Sjdp} 18233965Sjdp 18333965Sjdpstatic struct afswtch af_inet = { 18433965Sjdp .af_name = "inet", 18533965Sjdp .af_af = AF_INET, 18633965Sjdp .af_status = in_status, 18733965Sjdp .af_getaddr = in_getaddr, 18833965Sjdp .af_status_tunnel = in_status_tunnel, 18933965Sjdp .af_settunnel = in_set_tunnel, 19033965Sjdp .af_difaddr = SIOCDIFADDR, 19133965Sjdp .af_aifaddr = SIOCAIFADDR, 19233965Sjdp .af_ridreq = &in_ridreq, 19333965Sjdp .af_addreq = &in_addreq, 19433965Sjdp}; 19533965Sjdp 19660484Sobrienstatic __constructor void 19733965Sjdpinet_ctor(void) 19833965Sjdp{ 19933965Sjdp af_register(&af_inet); 20060484Sobrien} 20133965Sjdp