]> git.saurik.com Git - apple/network_cmds.git/blob - ifconfig.tproj/af_inet.c
network_cmds-606.40.2.tar.gz
[apple/network_cmds.git] / ifconfig.tproj / af_inet.c
1 /*
2 * Copyright (c) 2009-2011, 2020 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 #include <sys/types.h>
59 #include <sys/ioctl.h>
60 #include <sys/socket.h>
61 #include <net/if.h>
62
63 #include <err.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <unistd.h>
68 #include <ifaddrs.h>
69
70 #include <netinet/in.h>
71 #include <net/if_var.h> /* for struct ifaddr */
72 #include <netinet/in_var.h>
73 #include <arpa/inet.h>
74 #include <netdb.h>
75
76 #include "ifconfig.h"
77
78 static struct ifaliasreq in_addreq;
79 static struct ifreq in_ridreq;
80
81 static void
82 in_status(int s __unused, const struct ifaddrs *ifa)
83 {
84 struct sockaddr_in *sin, null_sin;
85
86 memset(&null_sin, 0, sizeof(null_sin));
87
88 sin = (struct sockaddr_in *)ifa->ifa_addr;
89 if (sin == NULL)
90 return;
91
92 printf("\tinet %s ", inet_ntoa(sin->sin_addr));
93
94 if (ifa->ifa_flags & IFF_POINTOPOINT) {
95 sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
96 if (sin == NULL)
97 sin = &null_sin;
98 printf("--> %s ", inet_ntoa(sin->sin_addr));
99 }
100
101 sin = (struct sockaddr_in *)ifa->ifa_netmask;
102 if (sin == NULL)
103 sin = &null_sin;
104 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
105
106 if (ifa->ifa_flags & IFF_BROADCAST) {
107 sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
108 if (sin != NULL && sin->sin_addr.s_addr != 0)
109 printf("broadcast %s", inet_ntoa(sin->sin_addr));
110 }
111 putchar('\n');
112 }
113
114 #define SIN(x) ((struct sockaddr_in *) &(x))
115 static struct sockaddr_in *sintab[] = {
116 SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
117 SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)
118 };
119
120 static void
121 in_getaddr(const char *s, int which)
122 {
123 #ifndef MIN
124 #define MIN(a,b) ((a)<(b)?(a):(b))
125 #endif /* MIN */
126 struct sockaddr_in *sin = sintab[which];
127 struct hostent *hp;
128 struct netent *np;
129
130 sin->sin_len = sizeof(*sin);
131 if (which != MASK)
132 sin->sin_family = AF_INET;
133
134 if (which == ADDR) {
135 char *p = NULL;
136
137 if((p = strrchr(s, '/')) != NULL) {
138 /* address is `name/masklen' */
139 int masklen;
140 int ret;
141 struct sockaddr_in *min = sintab[MASK];
142 *p = '\0';
143 ret = sscanf(p+1, "%u", &masklen);
144 if(ret != 1 || (masklen < 0 || masklen > 32)) {
145 *p = '/';
146 errx(1, "%s: bad value", s);
147 }
148 min->sin_len = sizeof(*min);
149 min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) &
150 0xffffffff);
151 }
152 }
153
154 if (inet_aton(s, &sin->sin_addr))
155 return;
156 if ((hp = gethostbyname(s)) != 0)
157 bcopy(hp->h_addr, (char *)&sin->sin_addr,
158 MIN(hp->h_length, sizeof(sin->sin_addr)));
159 else if ((np = getnetbyname(s)) != 0)
160 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
161 else
162 errx(1, "%s: bad value", s);
163 #undef MIN
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));
175 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
176
177 if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0)
178 return;
179 if (sa->sa_family != AF_INET)
180 return;
181 if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0)
182 src[0] = '\0';
183
184 if (ioctl(s, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0)
185 return;
186 if (sa->sa_family != AF_INET)
187 return;
188 if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0)
189 dst[0] = '\0';
190
191 printf("\ttunnel inet %s --> %s\n", src, dst);
192 }
193
194 static void
195 in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
196 {
197 struct ifaliasreq addreq;
198
199 memset(&addreq, 0, sizeof(addreq));
200 strlcpy(addreq.ifra_name, name, sizeof(addreq.ifra_name));
201 memcpy(&addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
202 memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len);
203
204 if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0)
205 warn("SIOCSIFPHYADDR");
206 }
207
208 static void
209 in_set_router(int s, int enable)
210 {
211 struct ifreq ifr;
212
213 bzero(&ifr, sizeof (ifr));
214 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
215 ifr.ifr_intval = enable;
216
217 if (ioctl(s, SIOCSETROUTERMODE, &ifr) < 0)
218 warn("SIOCSETROUTERMODE");
219 }
220
221 static int
222 routermode_from_string(char * str, int *mode_p)
223 {
224 int success = 1;
225
226 if (strcasecmp(str, "enabled") == 0) {
227 *mode_p = 1;
228 } else if (strcasecmp(str, "disabled") == 0) {
229 *mode_p = 0;
230 } else {
231 success = 0;
232 }
233 return (success);
234 }
235
236 static const char *
237 routermode_string(int mode)
238 {
239 const char * str;
240
241 switch (mode) {
242 case 0:
243 str = "disabled";
244 break;
245 case 1:
246 str = "enabled";
247 break;
248 default:
249 str = "<unknown>";
250 break;
251 }
252 return str;
253 }
254
255 static int
256 in_routermode(int s, int argc, char *const*argv)
257 {
258 struct ifreq ifr;
259 int ret;
260
261 bzero(&ifr, sizeof (ifr));
262 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
263 if (argc == 0) {
264 ret = 0;
265 #ifndef SIOCGETROUTERMODE
266 #define SIOCGETROUTERMODE _IOWR('i', 209, struct ifreq) /* get IPv4 router mode state */
267 #endif /* SIOCGETROUTERMODE */
268 if (ioctl(s, SIOCGETROUTERMODE, &ifr) < 0) {
269 if (argv != NULL) {
270 warn("SIOCGETROUTERMODE");
271 }
272 } else {
273 /* argv is NULL if we're called from status() */
274 printf("%s%s\n",
275 (argv == NULL) ? "\troutermode4: " : "",
276 routermode_string(ifr.ifr_intval));
277 }
278 ret = 0;
279 } else {
280 int mode;
281
282 if (routermode_from_string(argv[0], &mode) == 0) {
283 errx(EXIT_FAILURE,
284 "mode '%s' invalid, must be one of "
285 "disabled or enabled",
286 argv[0]);
287 }
288 ifr.ifr_intval = mode;
289 if (ioctl(s, SIOCSETROUTERMODE, &ifr) < 0) {
290 warn("SIOCSETROUTERMODE");
291 }
292 ret = 1;
293 }
294 return ret;
295 }
296
297 static struct afswtch af_inet = {
298 .af_name = "inet",
299 .af_af = AF_INET,
300 .af_status = in_status,
301 .af_getaddr = in_getaddr,
302 .af_status_tunnel = in_status_tunnel,
303 .af_settunnel = in_set_tunnel,
304 .af_setrouter = in_set_router,
305 .af_routermode = in_routermode,
306 .af_difaddr = SIOCDIFADDR,
307 .af_aifaddr = SIOCAIFADDR,
308 .af_ridreq = &in_ridreq,
309 .af_addreq = &in_addreq,
310 };
311
312 static __constructor void
313 inet_ctor(void)
314 {
315 af_register(&af_inet);
316 }