keep npartitions independent of byte order
[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
b14b214d 14static char sccsid[] = "@(#)ifconfig.c 4.18 (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 298 if ((p = afp) != NULL) {
b14b214d
MK
299 (*p->af_status)(1);
300 } else for (p = afs; p->af_name; p++) {
62e9bc4a 301 ifr.ifr_addr.sa_family = p->af_af;
b14b214d 302 (*p->af_status)(0);
62e9bc4a
KS
303 }
304}
305
b14b214d
MK
306in_status(force)
307 int force;
b3eab9f9
SL
308{
309 struct sockaddr_in *sin;
62e9bc4a 310 char *inet_ntoa();
b3eab9f9 311
37d62ab6 312 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
0fd5cf4f 313 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
b14b214d
MK
314 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
315 if (!force)
316 return;
0fd5cf4f 317 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
b14b214d
MK
318 } else
319 perror("ioctl (SIOCGIFADDR)");
0fd5cf4f 320 }
b3eab9f9 321 sin = (struct sockaddr_in *)&ifr.ifr_addr;
5868d993 322 printf("\tinet %s ", inet_ntoa(sin->sin_addr));
b14b214d
MK
323 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
324 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
325 if (errno != EADDRNOTAVAIL)
326 perror("ioctl (SIOCGIFNETMASK)");
327 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
328 } else
329 netmask.sin_addr =
330 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
40a42b7f 331 if (flags & IFF_POINTOPOINT) {
0fd5cf4f
MK
332 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
333 if (errno == EADDRNOTAVAIL)
334 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
335 else
b14b214d 336 perror("ioctl (SIOCGIFDSTADDR)");
0fd5cf4f 337 }
62e9bc4a 338 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
40a42b7f
TF
339 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
340 printf("--> %s ", inet_ntoa(sin->sin_addr));
341 }
0fd5cf4f 342 printf("netmask %x ", ntohl(netmask.sin_addr.s_addr));
0fd5cf4f 343 if (flags & IFF_BROADCAST) {
0fd5cf4f
MK
344 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
345 if (errno == EADDRNOTAVAIL)
b14b214d
MK
346 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
347 else
348 perror("ioctl (SIOCGIFADDR)");
0fd5cf4f 349 }
62e9bc4a 350 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
0fd5cf4f 351 sin = (struct sockaddr_in *)&ifr.ifr_addr;
b14b214d
MK
352 if (sin->sin_addr.s_addr != 0)
353 printf("broadcast %s", inet_ntoa(sin->sin_addr));
0fd5cf4f 354 }
f5f09b9d 355 putchar('\n');
b3eab9f9
SL
356}
357
62e9bc4a 358
b14b214d
MK
359xns_status(force)
360 int force;
62e9bc4a
KS
361{
362 struct sockaddr_ns *sns;
62e9bc4a
KS
363
364 close(s);
365 s = socket(AF_NS, SOCK_DGRAM, 0);
366 if (s < 0) {
63f46c0f
KS
367 if (errno == EAFNOSUPPORT)
368 return;
62e9bc4a
KS
369 perror("ifconfig: socket");
370 exit(1);
371 }
372 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
b14b214d
MK
373 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
374 if (!force)
375 return;
376 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
377 } else
378 perror("ioctl (SIOCGIFADDR)");
62e9bc4a
KS
379 }
380 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
381 sns = (struct sockaddr_ns *)&ifr.ifr_addr;
f5f09b9d 382 printf("\tns %s ", ns_ntoa(sns->sns_addr));
90a22cbc
KS
383 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
384 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
385 if (errno == EADDRNOTAVAIL)
386 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
387 else
388 Perror("ioctl (SIOCGIFDSTADDR)");
389 }
390 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
391 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
392 printf("--> %s ", ns_ntoa(sns->sns_addr));
393 }
62e9bc4a
KS
394 putchar('\n');
395}
396
b3eab9f9
SL
397Perror(cmd)
398 char *cmd;
399{
400 extern int errno;
401
402 fprintf(stderr, "ifconfig: ");
403 switch (errno) {
404
405 case ENXIO:
62e9bc4a 406 fprintf(stderr, "%s: no such interface\n", cmd);
b3eab9f9
SL
407 break;
408
409 case EPERM:
9f1b5d96 410 fprintf(stderr, "%s: permission denied\n", cmd);
b3eab9f9
SL
411 break;
412
413 default:
414 perror(cmd);
415 }
416 exit(1);
417}
418
419struct in_addr inet_makeaddr();
420
62e9bc4a 421in_getaddr(s, saddr)
b3eab9f9 422 char *s;
62e9bc4a 423 struct sockaddr *saddr;
b3eab9f9 424{
62e9bc4a 425 register struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
b3eab9f9
SL
426 struct hostent *hp;
427 struct netent *np;
428 int val;
429
0fd5cf4f
MK
430 sin->sin_family = AF_INET;
431 val = inet_addr(s);
432 if (val != -1) {
433 sin->sin_addr.s_addr = val;
434 return;
435 }
b3eab9f9
SL
436 hp = gethostbyname(s);
437 if (hp) {
438 sin->sin_family = hp->h_addrtype;
439 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
440 return;
441 }
442 np = getnetbyname(s);
443 if (np) {
444 sin->sin_family = np->n_addrtype;
445 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
446 return;
447 }
b3eab9f9
SL
448 fprintf(stderr, "%s: bad value\n", s);
449 exit(1);
450}
451
452/*
453 * Print a value a la the %b format of the kernel's printf
454 */
455printb(s, v, bits)
456 char *s;
457 register char *bits;
458 register unsigned short v;
459{
460 register int i, any = 0;
461 register char c;
462
463 if (bits && *bits == 8)
464 printf("%s=%o", s, v);
465 else
466 printf("%s=%x", s, v);
467 bits++;
468 if (bits) {
469 putchar('<');
470 while (i = *bits++) {
471 if (v & (1 << (i-1))) {
472 if (any)
473 putchar(',');
474 any = 1;
475 for (; (c = *bits) > 32; bits++)
476 putchar(c);
477 } else
478 for (; *bits > 32; bits++)
479 ;
480 }
481 putchar('>');
482 }
483}
62e9bc4a 484
62e9bc4a
KS
485xns_getaddr(addr, saddr)
486char *addr;
487struct sockaddr *saddr;
488{
90a22cbc
KS
489 struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr;
490 struct ns_addr ns_addr();
62e9bc4a 491 sns->sns_family = AF_NS;
90a22cbc 492 sns->sns_addr = ns_addr(addr);
62e9bc4a 493}