BSD 4_3_Net_1 release
[unix-history] / ifconfig / ifconfig.c
CommitLineData
0fd5cf4f
MK
1/*
2 * Copyright (c) 1983 Regents of the University of California.
40c992d9
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
0fd5cf4f
MK
16 */
17
b3eab9f9 18#ifndef lint
0fd5cf4f
MK
19char copyright[] =
20"@(#) Copyright (c) 1983 Regents of the University of California.\n\
21 All rights reserved.\n";
40c992d9 22#endif /* not lint */
0fd5cf4f
MK
23
24#ifndef lint
ca67e7b4 25static char sccsid[] = "@(#)ifconfig.c 4.21 (Berkeley) 7/1/88";
40c992d9 26#endif /* not lint */
0fd5cf4f 27
b3eab9f9
SL
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/ioctl.h>
31
b3eab9f9 32#include <net/if.h>
62e9bc4a
KS
33#include <netinet/in.h>
34
35#define NSIP
36#include <netns/ns.h>
37#include <netns/ns_if.h>
b3eab9f9
SL
38
39#include <stdio.h>
40#include <errno.h>
41#include <ctype.h>
42#include <netdb.h>
43
62e9bc4a 44extern int errno;
b3eab9f9
SL
45struct ifreq ifr;
46struct sockaddr_in sin = { AF_INET };
0fd5cf4f
MK
47struct sockaddr_in broadaddr;
48struct sockaddr_in netmask = { AF_INET };
62e9bc4a 49struct sockaddr_in ipdst = { AF_INET };
b3eab9f9 50char name[30];
0fd5cf4f 51int flags;
f5f09b9d 52int metric;
dea973a0 53int setaddr;
0fd5cf4f
MK
54int setmask;
55int setbroadaddr;
62e9bc4a 56int setipdst;
b3eab9f9 57int s;
0fd5cf4f
MK
58extern int errno;
59
60int setifflags(), setifaddr(), setifdstaddr(), setifnetmask();
f5f09b9d 61int setifmetric(), setifbroadaddr(), setifipdst();
b3eab9f9 62
0fd5cf4f 63#define NEXTARG 0xffffff
b3eab9f9
SL
64
65struct cmd {
66 char *c_name;
0fd5cf4f 67 int c_parameter; /* NEXTARG means next argv */
b3eab9f9
SL
68 int (*c_func)();
69} cmds[] = {
70 { "up", IFF_UP, setifflags } ,
71 { "down", -IFF_UP, setifflags },
72 { "trailers", -IFF_NOTRAILERS,setifflags },
73 { "-trailers", IFF_NOTRAILERS, setifflags },
1095926d
MK
74 { "arp", -IFF_NOARP, setifflags },
75 { "-arp", IFF_NOARP, setifflags },
717eb130
CL
76 { "debug", IFF_DEBUG, setifflags },
77 { "-debug", -IFF_DEBUG, setifflags },
a390ced5 78#ifdef notdef
0fd5cf4f 79#define EN_SWABIPS 0x1000
a390ced5
SL
80 { "swabips", EN_SWABIPS, setifflags },
81 { "-swabips", -EN_SWABIPS, setifflags },
82#endif
0fd5cf4f 83 { "netmask", NEXTARG, setifnetmask },
f5f09b9d 84 { "metric", NEXTARG, setifmetric },
0fd5cf4f 85 { "broadcast", NEXTARG, setifbroadaddr },
62e9bc4a 86 { "ipdst", NEXTARG, setifipdst },
b3eab9f9 87 { 0, 0, setifaddr },
40a42b7f 88 { 0, 0, setifdstaddr },
b3eab9f9
SL
89};
90
62e9bc4a
KS
91/*
92 * XNS support liberally adapted from
93 * code written at the University of Maryland
94 * principally by James O'Toole and Chris Torek.
95 */
96
97int in_status(), in_getaddr();
98int xns_status(), xns_getaddr();
99
100/* Known address families */
101struct afswtch {
102 char *af_name;
103 short af_af;
104 int (*af_status)();
105 int (*af_getaddr)();
106} afs[] = {
107 { "inet", AF_INET, in_status, in_getaddr },
108 { "ns", AF_NS, xns_status, xns_getaddr },
109 { 0, 0, 0, 0 }
110};
111
112struct afswtch *afp; /*the address family being set or asked about*/
113
b3eab9f9
SL
114main(argc, argv)
115 int argc;
116 char *argv[];
117{
62e9bc4a 118 int af = AF_INET;
37d62ab6 119
b3eab9f9 120 if (argc < 2) {
30078595 121 fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s",
f5f09b9d
MK
122 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]",
123 "[ netmask mask ] ]\n",
124 "\t[ metric n ]\n",
125 "\t[ trailers | -trailers ]\n",
126 "\t[ arp | -arp ]\n");
b3eab9f9
SL
127 exit(1);
128 }
62e9bc4a 129 argc--, argv++;
63f46c0f 130 strncpy(name, *argv, sizeof(name));
62e9bc4a
KS
131 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
132 argc--, argv++;
133 if (argc > 0) {
134 struct afswtch *myafp;
135
136 for (myafp = afp = afs; myafp->af_name; myafp++)
137 if (strcmp(myafp->af_name, *argv) == 0) {
138 afp = myafp; argc--; argv++;
139 break;
140 }
141 af = ifr.ifr_addr.sa_family = afp->af_af;
142 }
143 s = socket(af, SOCK_DGRAM, 0);
b3eab9f9
SL
144 if (s < 0) {
145 perror("ifconfig: socket");
146 exit(1);
147 }
b3eab9f9
SL
148 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
149 Perror("ioctl (SIOCGIFFLAGS)");
150 exit(1);
151 }
62e9bc4a 152 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
0fd5cf4f 153 flags = ifr.ifr_flags;
f5f09b9d
MK
154 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
155 perror("ioctl (SIOCGIFMETRIC)");
156 else
157 metric = ifr.ifr_metric;
b3eab9f9
SL
158 if (argc == 0) {
159 status();
160 exit(0);
161 }
162 while (argc > 0) {
163 register struct cmd *p;
164
165 for (p = cmds; p->c_name; p++)
166 if (strcmp(*argv, p->c_name) == 0)
167 break;
40a42b7f
TF
168 if (p->c_name == 0 && setaddr)
169 p++; /* got src, do dst */
0fd5cf4f
MK
170 if (p->c_func) {
171 if (p->c_parameter == NEXTARG) {
172 (*p->c_func)(argv[1]);
173 argc--, argv++;
174 } else
175 (*p->c_func)(*argv, p->c_parameter);
176 }
b3eab9f9
SL
177 argc--, argv++;
178 }
37d62ab6 179 if ((setmask || setaddr) && (af == AF_INET)) {
0fd5cf4f
MK
180 /*
181 * If setting the address and not the mask,
182 * clear any existing mask and the kernel will then
183 * assign the default. If setting both,
184 * set the mask first, so the address will be
185 * interpreted correctly.
186 */
0fd5cf4f
MK
187 ifr.ifr_addr = *(struct sockaddr *)&netmask;
188 if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0)
189 Perror("ioctl (SIOCSIFNETMASK)");
190 }
62e9bc4a
KS
191 if (setipdst && af==AF_NS) {
192 struct nsip_req rq;
193 int size = sizeof(rq);
194
195 rq.rq_ns = *(struct sockaddr *) &sin;
196 rq.rq_ip = *(struct sockaddr *) &ipdst;
197
198 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
199 Perror("Encapsulation Routing");
200 setaddr = 0;
201 }
dea973a0 202 if (setaddr) {
dea973a0
MK
203 ifr.ifr_addr = *(struct sockaddr *) &sin;
204 if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0)
205 Perror("ioctl (SIOCSIFADDR)");
206 }
0fd5cf4f 207 if (setbroadaddr) {
0fd5cf4f
MK
208 ifr.ifr_addr = *(struct sockaddr *)&broadaddr;
209 if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0)
210 Perror("ioctl (SIOCSIFBRDADDR)");
211 }
b3eab9f9
SL
212 exit(0);
213}
214
215/*ARGSUSED*/
216setifaddr(addr, param)
217 char *addr;
62e9bc4a 218 short param;
b3eab9f9 219{
dea973a0
MK
220 /*
221 * Delay the ioctl to set the interface addr until flags are all set.
222 * The address interpretation may depend on the flags,
223 * and the flags may change when the address is set.
a9575a9a 224 */
dea973a0 225 setaddr++;
62e9bc4a 226 (*afp->af_getaddr)(addr, &sin);
b3eab9f9
SL
227}
228
0fd5cf4f
MK
229setifnetmask(addr)
230 char *addr;
231{
62e9bc4a 232 in_getaddr(addr, &netmask);
0fd5cf4f
MK
233 setmask++;
234}
235
236setifbroadaddr(addr)
237 char *addr;
238{
62e9bc4a 239 (*afp->af_getaddr)(addr, &broadaddr);
0fd5cf4f
MK
240 setbroadaddr++;
241}
242
62e9bc4a
KS
243setifipdst(addr)
244 char *addr;
245{
246 in_getaddr(addr, &ipdst);
247 setipdst++;
248}
249
40a42b7f
TF
250/*ARGSUSED*/
251setifdstaddr(addr, param)
252 char *addr;
253 int param;
254{
255
62e9bc4a 256 (*afp->af_getaddr)(addr, &ifr.ifr_addr);
40a42b7f
TF
257 if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0)
258 Perror("ioctl (SIOCSIFDSTADDR)");
259}
260
2c4ef00e
SL
261setifflags(vname, value)
262 char *vname;
62e9bc4a 263 short value;
b3eab9f9 264{
62e9bc4a
KS
265 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
266 Perror("ioctl (SIOCGIFFLAGS)");
267 exit(1);
268 }
269 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
270 flags = ifr.ifr_flags;
b3eab9f9
SL
271
272 if (value < 0) {
273 value = -value;
0fd5cf4f 274 flags &= ~value;
b3eab9f9 275 } else
0fd5cf4f 276 flags |= value;
0fd5cf4f 277 ifr.ifr_flags = flags;
b3eab9f9 278 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
2c4ef00e 279 Perror(vname);
b3eab9f9
SL
280}
281
f5f09b9d
MK
282setifmetric(val)
283 char *val;
284{
285 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
286 ifr.ifr_metric = atoi(val);
287 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
288 perror("ioctl (set metric)");
289}
290
291#define IFFBITS \
292"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
293"
294
62e9bc4a
KS
295/*
296 * Print the status of the interface. If an address family was
297 * specified, show it and it only; otherwise, show them all.
298 */
b3eab9f9 299status()
62e9bc4a
KS
300{
301 register struct afswtch *p = afp;
302 short af = ifr.ifr_addr.sa_family;
303
f5f09b9d
MK
304 printf("%s: ", name);
305 printb("flags", flags, IFFBITS);
306 if (metric)
307 printf(" metric %d", metric);
308 putchar('\n');
62e9bc4a 309 if ((p = afp) != NULL) {
b14b214d
MK
310 (*p->af_status)(1);
311 } else for (p = afs; p->af_name; p++) {
62e9bc4a 312 ifr.ifr_addr.sa_family = p->af_af;
b14b214d 313 (*p->af_status)(0);
62e9bc4a
KS
314 }
315}
316
b14b214d
MK
317in_status(force)
318 int force;
b3eab9f9
SL
319{
320 struct sockaddr_in *sin;
62e9bc4a 321 char *inet_ntoa();
b3eab9f9 322
37d62ab6 323 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
0fd5cf4f 324 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
b14b214d
MK
325 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
326 if (!force)
327 return;
0fd5cf4f 328 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
b14b214d
MK
329 } else
330 perror("ioctl (SIOCGIFADDR)");
0fd5cf4f 331 }
b3eab9f9 332 sin = (struct sockaddr_in *)&ifr.ifr_addr;
5868d993 333 printf("\tinet %s ", inet_ntoa(sin->sin_addr));
b14b214d
MK
334 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
335 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
336 if (errno != EADDRNOTAVAIL)
337 perror("ioctl (SIOCGIFNETMASK)");
338 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
339 } else
340 netmask.sin_addr =
341 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
40a42b7f 342 if (flags & IFF_POINTOPOINT) {
0fd5cf4f
MK
343 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
344 if (errno == EADDRNOTAVAIL)
345 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
346 else
b14b214d 347 perror("ioctl (SIOCGIFDSTADDR)");
0fd5cf4f 348 }
62e9bc4a 349 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
40a42b7f
TF
350 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
351 printf("--> %s ", inet_ntoa(sin->sin_addr));
352 }
0fd5cf4f 353 printf("netmask %x ", ntohl(netmask.sin_addr.s_addr));
0fd5cf4f 354 if (flags & IFF_BROADCAST) {
0fd5cf4f
MK
355 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
356 if (errno == EADDRNOTAVAIL)
b14b214d
MK
357 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
358 else
359 perror("ioctl (SIOCGIFADDR)");
0fd5cf4f 360 }
62e9bc4a 361 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
0fd5cf4f 362 sin = (struct sockaddr_in *)&ifr.ifr_addr;
b14b214d
MK
363 if (sin->sin_addr.s_addr != 0)
364 printf("broadcast %s", inet_ntoa(sin->sin_addr));
0fd5cf4f 365 }
f5f09b9d 366 putchar('\n');
b3eab9f9
SL
367}
368
62e9bc4a 369
b14b214d
MK
370xns_status(force)
371 int force;
62e9bc4a
KS
372{
373 struct sockaddr_ns *sns;
62e9bc4a
KS
374
375 close(s);
376 s = socket(AF_NS, SOCK_DGRAM, 0);
377 if (s < 0) {
cd2e8e25 378 if (errno == EPROTONOSUPPORT)
63f46c0f 379 return;
62e9bc4a
KS
380 perror("ifconfig: socket");
381 exit(1);
382 }
383 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
b14b214d
MK
384 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
385 if (!force)
386 return;
387 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
388 } else
389 perror("ioctl (SIOCGIFADDR)");
62e9bc4a
KS
390 }
391 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
392 sns = (struct sockaddr_ns *)&ifr.ifr_addr;
f5f09b9d 393 printf("\tns %s ", ns_ntoa(sns->sns_addr));
90a22cbc
KS
394 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
395 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
396 if (errno == EADDRNOTAVAIL)
397 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
398 else
399 Perror("ioctl (SIOCGIFDSTADDR)");
400 }
401 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
402 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
403 printf("--> %s ", ns_ntoa(sns->sns_addr));
404 }
62e9bc4a
KS
405 putchar('\n');
406}
407
b3eab9f9
SL
408Perror(cmd)
409 char *cmd;
410{
411 extern int errno;
412
413 fprintf(stderr, "ifconfig: ");
414 switch (errno) {
415
416 case ENXIO:
62e9bc4a 417 fprintf(stderr, "%s: no such interface\n", cmd);
b3eab9f9
SL
418 break;
419
420 case EPERM:
9f1b5d96 421 fprintf(stderr, "%s: permission denied\n", cmd);
b3eab9f9
SL
422 break;
423
424 default:
425 perror(cmd);
426 }
427 exit(1);
428}
429
430struct in_addr inet_makeaddr();
431
62e9bc4a 432in_getaddr(s, saddr)
b3eab9f9 433 char *s;
62e9bc4a 434 struct sockaddr *saddr;
b3eab9f9 435{
62e9bc4a 436 register struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
b3eab9f9
SL
437 struct hostent *hp;
438 struct netent *np;
439 int val;
440
0fd5cf4f
MK
441 sin->sin_family = AF_INET;
442 val = inet_addr(s);
443 if (val != -1) {
444 sin->sin_addr.s_addr = val;
445 return;
446 }
b3eab9f9
SL
447 hp = gethostbyname(s);
448 if (hp) {
449 sin->sin_family = hp->h_addrtype;
450 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
451 return;
452 }
453 np = getnetbyname(s);
454 if (np) {
455 sin->sin_family = np->n_addrtype;
456 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
457 return;
458 }
b3eab9f9
SL
459 fprintf(stderr, "%s: bad value\n", s);
460 exit(1);
461}
462
463/*
464 * Print a value a la the %b format of the kernel's printf
465 */
466printb(s, v, bits)
467 char *s;
468 register char *bits;
469 register unsigned short v;
470{
471 register int i, any = 0;
472 register char c;
473
474 if (bits && *bits == 8)
475 printf("%s=%o", s, v);
476 else
477 printf("%s=%x", s, v);
478 bits++;
479 if (bits) {
480 putchar('<');
481 while (i = *bits++) {
482 if (v & (1 << (i-1))) {
483 if (any)
484 putchar(',');
485 any = 1;
486 for (; (c = *bits) > 32; bits++)
487 putchar(c);
488 } else
489 for (; *bits > 32; bits++)
490 ;
491 }
492 putchar('>');
493 }
494}
62e9bc4a 495
62e9bc4a
KS
496xns_getaddr(addr, saddr)
497char *addr;
498struct sockaddr *saddr;
499{
90a22cbc
KS
500 struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr;
501 struct ns_addr ns_addr();
62e9bc4a 502 sns->sns_family = AF_NS;
90a22cbc 503 sns->sns_addr = ns_addr(addr);
62e9bc4a 504}