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