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