122ce4affSfengbojiang /*-
222ce4affSfengbojiang * SPDX-License-Identifier: BSD-3-Clause
322ce4affSfengbojiang *
4df6ad731Slogwang * Copyright (c) 1983, 1993
5df6ad731Slogwang * The Regents of the University of California. All rights reserved.
6df6ad731Slogwang *
7df6ad731Slogwang * Redistribution and use in source and binary forms, with or without
8df6ad731Slogwang * modification, are permitted provided that the following conditions
9df6ad731Slogwang * are met:
10df6ad731Slogwang * 1. Redistributions of source code must retain the above copyright
11df6ad731Slogwang * notice, this list of conditions and the following disclaimer.
12df6ad731Slogwang * 2. Redistributions in binary form must reproduce the above copyright
13df6ad731Slogwang * notice, this list of conditions and the following disclaimer in the
14df6ad731Slogwang * documentation and/or other materials provided with the distribution.
1522ce4affSfengbojiang * 3. Neither the name of the University nor the names of its contributors
16df6ad731Slogwang * may be used to endorse or promote products derived from this software
17df6ad731Slogwang * without specific prior written permission.
18df6ad731Slogwang *
19df6ad731Slogwang * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df6ad731Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df6ad731Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df6ad731Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df6ad731Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df6ad731Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df6ad731Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df6ad731Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df6ad731Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df6ad731Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df6ad731Slogwang * SUCH DAMAGE.
30df6ad731Slogwang */
31df6ad731Slogwang
32df6ad731Slogwang #ifndef lint
33df6ad731Slogwang static const char rcsid[] =
34df6ad731Slogwang "$FreeBSD$";
35df6ad731Slogwang #endif /* not lint */
36df6ad731Slogwang
37df6ad731Slogwang #include <sys/param.h>
38df6ad731Slogwang #include <sys/ioctl.h>
39df6ad731Slogwang #include <sys/socket.h>
40df6ad731Slogwang #include <net/if.h>
41df6ad731Slogwang
42df6ad731Slogwang #include <ctype.h>
43df6ad731Slogwang #include <err.h>
44df6ad731Slogwang #include <stdio.h>
45df6ad731Slogwang #include <stdlib.h>
46df6ad731Slogwang #include <string.h>
47df6ad731Slogwang #include <unistd.h>
48df6ad731Slogwang #include <ifaddrs.h>
49df6ad731Slogwang
50df6ad731Slogwang #include <netinet/in.h>
51df6ad731Slogwang #include <netinet/in_var.h>
52df6ad731Slogwang #include <arpa/inet.h>
53df6ad731Slogwang #include <netdb.h>
54df6ad731Slogwang
55df6ad731Slogwang #include "ifconfig.h"
56df6ad731Slogwang
57df6ad731Slogwang static struct in_aliasreq in_addreq;
58df6ad731Slogwang static struct ifreq in_ridreq;
59df6ad731Slogwang static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/
60df6ad731Slogwang extern char *f_inet, *f_addr;
61df6ad731Slogwang
62df6ad731Slogwang static void
in_status(int s __unused,const struct ifaddrs * ifa)63df6ad731Slogwang in_status(int s __unused, const struct ifaddrs *ifa)
64df6ad731Slogwang {
65df6ad731Slogwang struct sockaddr_in *sin, null_sin;
66*d4a07e70Sfengbojiang #ifndef FSTACK
67df6ad731Slogwang int error, n_flags;
68*d4a07e70Sfengbojiang #endif
69df6ad731Slogwang
70df6ad731Slogwang memset(&null_sin, 0, sizeof(null_sin));
71df6ad731Slogwang
72df6ad731Slogwang sin = (struct sockaddr_in *)ifa->ifa_addr;
73df6ad731Slogwang if (sin == NULL)
74df6ad731Slogwang return;
75df6ad731Slogwang
76*d4a07e70Sfengbojiang #ifndef FSTACK
77df6ad731Slogwang if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
78df6ad731Slogwang n_flags = 0;
79df6ad731Slogwang else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
80df6ad731Slogwang n_flags = NI_NOFQDN;
81df6ad731Slogwang else
82df6ad731Slogwang n_flags = NI_NUMERICHOST;
83df6ad731Slogwang
84df6ad731Slogwang error = getnameinfo((struct sockaddr *)sin, sin->sin_len, addr_buf,
85df6ad731Slogwang sizeof(addr_buf), NULL, 0, n_flags);
86df6ad731Slogwang
87df6ad731Slogwang if (error)
88*d4a07e70Sfengbojiang #endif
89df6ad731Slogwang inet_ntop(AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf));
90df6ad731Slogwang
91df6ad731Slogwang printf("\tinet %s", addr_buf);
92df6ad731Slogwang
93df6ad731Slogwang if (ifa->ifa_flags & IFF_POINTOPOINT) {
94df6ad731Slogwang sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
95df6ad731Slogwang if (sin == NULL)
96df6ad731Slogwang sin = &null_sin;
97df6ad731Slogwang printf(" --> %s", inet_ntoa(sin->sin_addr));
98df6ad731Slogwang }
99df6ad731Slogwang
100df6ad731Slogwang sin = (struct sockaddr_in *)ifa->ifa_netmask;
101df6ad731Slogwang if (sin == NULL)
102df6ad731Slogwang sin = &null_sin;
103df6ad731Slogwang if (f_inet != NULL && strcmp(f_inet, "cidr") == 0) {
104df6ad731Slogwang int cidr = 32;
105df6ad731Slogwang unsigned long smask;
106df6ad731Slogwang
107df6ad731Slogwang smask = ntohl(sin->sin_addr.s_addr);
108df6ad731Slogwang while ((smask & 1) == 0) {
109df6ad731Slogwang smask = smask >> 1;
110df6ad731Slogwang cidr--;
111df6ad731Slogwang if (cidr == 0)
112df6ad731Slogwang break;
113df6ad731Slogwang }
114df6ad731Slogwang printf("/%d", cidr);
115df6ad731Slogwang } else if (f_inet != NULL && strcmp(f_inet, "dotted") == 0)
116df6ad731Slogwang printf(" netmask %s", inet_ntoa(sin->sin_addr));
117df6ad731Slogwang else
118df6ad731Slogwang printf(" netmask 0x%lx", (unsigned long)ntohl(sin->sin_addr.s_addr));
119df6ad731Slogwang
120df6ad731Slogwang if (ifa->ifa_flags & IFF_BROADCAST) {
121df6ad731Slogwang sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
122df6ad731Slogwang if (sin != NULL && sin->sin_addr.s_addr != 0)
123df6ad731Slogwang printf(" broadcast %s", inet_ntoa(sin->sin_addr));
124df6ad731Slogwang }
125df6ad731Slogwang
126df6ad731Slogwang print_vhid(ifa, " ");
127df6ad731Slogwang
128df6ad731Slogwang putchar('\n');
129df6ad731Slogwang }
130df6ad731Slogwang
131df6ad731Slogwang #define SIN(x) ((struct sockaddr_in *) &(x))
132df6ad731Slogwang static struct sockaddr_in *sintab[] = {
133df6ad731Slogwang SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
134df6ad731Slogwang SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)
135df6ad731Slogwang };
136df6ad731Slogwang
137df6ad731Slogwang static void
in_getaddr(const char * s,int which)138df6ad731Slogwang in_getaddr(const char *s, int which)
139df6ad731Slogwang {
140df6ad731Slogwang struct sockaddr_in *sin = sintab[which];
141*d4a07e70Sfengbojiang #ifndef FSTACK
142df6ad731Slogwang struct hostent *hp;
143df6ad731Slogwang struct netent *np;
144*d4a07e70Sfengbojiang #endif
145df6ad731Slogwang
146df6ad731Slogwang sin->sin_len = sizeof(*sin);
147df6ad731Slogwang sin->sin_family = AF_INET;
148df6ad731Slogwang
149df6ad731Slogwang if (which == ADDR) {
150df6ad731Slogwang char *p = NULL;
151df6ad731Slogwang
152df6ad731Slogwang if((p = strrchr(s, '/')) != NULL) {
153df6ad731Slogwang const char *errstr;
154df6ad731Slogwang /* address is `name/masklen' */
155df6ad731Slogwang int masklen;
156df6ad731Slogwang struct sockaddr_in *min = sintab[MASK];
157df6ad731Slogwang *p = '\0';
158df6ad731Slogwang if (!isdigit(*(p + 1)))
159df6ad731Slogwang errstr = "invalid";
160df6ad731Slogwang else
161df6ad731Slogwang masklen = (int)strtonum(p + 1, 0, 32, &errstr);
162df6ad731Slogwang if (errstr != NULL) {
163df6ad731Slogwang *p = '/';
164df6ad731Slogwang errx(1, "%s: bad value (width %s)", s, errstr);
165df6ad731Slogwang }
166df6ad731Slogwang min->sin_family = AF_INET;
167df6ad731Slogwang min->sin_len = sizeof(*min);
168df6ad731Slogwang min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) &
169df6ad731Slogwang 0xffffffff);
170df6ad731Slogwang }
171df6ad731Slogwang }
172df6ad731Slogwang
173df6ad731Slogwang if (inet_aton(s, &sin->sin_addr))
174df6ad731Slogwang return;
175*d4a07e70Sfengbojiang #ifdef FSTACK
176*d4a07e70Sfengbojiang else
177*d4a07e70Sfengbojiang errx(1, "%s: bad value", s);
178*d4a07e70Sfengbojiang #else
179df6ad731Slogwang if ((hp = gethostbyname(s)) != NULL)
180df6ad731Slogwang bcopy(hp->h_addr, (char *)&sin->sin_addr,
181df6ad731Slogwang MIN((size_t)hp->h_length, sizeof(sin->sin_addr)));
182df6ad731Slogwang else if ((np = getnetbyname(s)) != NULL)
183df6ad731Slogwang sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
184df6ad731Slogwang else
185df6ad731Slogwang errx(1, "%s: bad value", s);
186*d4a07e70Sfengbojiang #endif
187df6ad731Slogwang }
188df6ad731Slogwang
189df6ad731Slogwang static void
in_status_tunnel(int s)190df6ad731Slogwang in_status_tunnel(int s)
191df6ad731Slogwang {
192df6ad731Slogwang char src[NI_MAXHOST];
193df6ad731Slogwang char dst[NI_MAXHOST];
194df6ad731Slogwang struct ifreq ifr;
195df6ad731Slogwang const struct sockaddr *sa = (const struct sockaddr *) &ifr.ifr_addr;
196*d4a07e70Sfengbojiang #ifdef FSTACK
197*d4a07e70Sfengbojiang const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
198*d4a07e70Sfengbojiang #endif
199df6ad731Slogwang
200df6ad731Slogwang memset(&ifr, 0, sizeof(ifr));
201df6ad731Slogwang strlcpy(ifr.ifr_name, name, IFNAMSIZ);
202df6ad731Slogwang
203df6ad731Slogwang if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0)
204df6ad731Slogwang return;
205df6ad731Slogwang if (sa->sa_family != AF_INET)
206df6ad731Slogwang return;
207*d4a07e70Sfengbojiang #ifndef FSTACK
208df6ad731Slogwang if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0)
209df6ad731Slogwang src[0] = '\0';
210*d4a07e70Sfengbojiang #else
211*d4a07e70Sfengbojiang if (inet_ntop(AF_INET, &sin->sin_addr, src, sizeof(src)) == NULL)
212*d4a07e70Sfengbojiang return;
213*d4a07e70Sfengbojiang #endif
214df6ad731Slogwang
215df6ad731Slogwang if (ioctl(s, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0)
216df6ad731Slogwang return;
217df6ad731Slogwang if (sa->sa_family != AF_INET)
218df6ad731Slogwang return;
219*d4a07e70Sfengbojiang #ifndef FSTACK
220df6ad731Slogwang if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0)
221df6ad731Slogwang dst[0] = '\0';
222*d4a07e70Sfengbojiang #else
223*d4a07e70Sfengbojiang if (inet_ntop(AF_INET, &sin->sin_addr, dst, sizeof(dst)) == NULL)
224*d4a07e70Sfengbojiang return;
225*d4a07e70Sfengbojiang #endif
226df6ad731Slogwang
227df6ad731Slogwang printf("\ttunnel inet %s --> %s\n", src, dst);
228df6ad731Slogwang }
229df6ad731Slogwang
230df6ad731Slogwang static void
in_set_tunnel(int s,struct addrinfo * srcres,struct addrinfo * dstres)231df6ad731Slogwang in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
232df6ad731Slogwang {
233df6ad731Slogwang struct in_aliasreq addreq;
234df6ad731Slogwang
235df6ad731Slogwang memset(&addreq, 0, sizeof(addreq));
236df6ad731Slogwang strlcpy(addreq.ifra_name, name, IFNAMSIZ);
237df6ad731Slogwang memcpy(&addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
238df6ad731Slogwang memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len);
239df6ad731Slogwang
240df6ad731Slogwang if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0)
241df6ad731Slogwang warn("SIOCSIFPHYADDR");
242df6ad731Slogwang }
243df6ad731Slogwang
244df6ad731Slogwang static struct afswtch af_inet = {
245df6ad731Slogwang .af_name = "inet",
246df6ad731Slogwang .af_af = AF_INET,
247df6ad731Slogwang .af_status = in_status,
248df6ad731Slogwang .af_getaddr = in_getaddr,
249df6ad731Slogwang .af_status_tunnel = in_status_tunnel,
250df6ad731Slogwang .af_settunnel = in_set_tunnel,
251df6ad731Slogwang .af_difaddr = SIOCDIFADDR,
252df6ad731Slogwang .af_aifaddr = SIOCAIFADDR,
253df6ad731Slogwang .af_ridreq = &in_ridreq,
254df6ad731Slogwang .af_addreq = &in_addreq,
255df6ad731Slogwang };
256df6ad731Slogwang
257df6ad731Slogwang static __constructor void
inet_ctor(void)258df6ad731Slogwang inet_ctor(void)
259df6ad731Slogwang {
260*d4a07e70Sfengbojiang #ifndef FSTACK
261df6ad731Slogwang #ifndef RESCUE
262df6ad731Slogwang if (!feature_present("inet"))
263df6ad731Slogwang return;
264df6ad731Slogwang #endif
265*d4a07e70Sfengbojiang #endif
266df6ad731Slogwang af_register(&af_inet);
267df6ad731Slogwang }
268