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