name the data field for echo, etc.
[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
6066ec2d 14static char sccsid[] = "@(#)ifconfig.c 4.16 (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;
b3eab9f9 108 if (argc < 2) {
f5f09b9d
MK
109 fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s",
110 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]",
111 "[ netmask mask ] ]\n",
112 "\t[ metric n ]\n",
113 "\t[ trailers | -trailers ]\n",
114 "\t[ arp | -arp ]\n");
b3eab9f9
SL
115 exit(1);
116 }
62e9bc4a 117 argc--, argv++;
63f46c0f 118 strncpy(name, *argv, sizeof(name));
62e9bc4a
KS
119 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
120 argc--, argv++;
121 if (argc > 0) {
122 struct afswtch *myafp;
123
124 for (myafp = afp = afs; myafp->af_name; myafp++)
125 if (strcmp(myafp->af_name, *argv) == 0) {
126 afp = myafp; argc--; argv++;
127 break;
128 }
129 af = ifr.ifr_addr.sa_family = afp->af_af;
130 }
131 s = socket(af, SOCK_DGRAM, 0);
b3eab9f9
SL
132 if (s < 0) {
133 perror("ifconfig: socket");
134 exit(1);
135 }
b3eab9f9
SL
136 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
137 Perror("ioctl (SIOCGIFFLAGS)");
138 exit(1);
139 }
62e9bc4a 140 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
0fd5cf4f 141 flags = ifr.ifr_flags;
f5f09b9d
MK
142 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
143 perror("ioctl (SIOCGIFMETRIC)");
144 else
145 metric = ifr.ifr_metric;
62e9bc4a
KS
146 if (af == AF_INET) {
147 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
148 if (errno != EADDRNOTAVAIL)
149 Perror("ioctl (SIOCGIFNETMASK)");
150 } else
151 netmask.sin_addr =
152 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
153 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
154 }
b3eab9f9
SL
155 if (argc == 0) {
156 status();
157 exit(0);
158 }
159 while (argc > 0) {
160 register struct cmd *p;
161
162 for (p = cmds; p->c_name; p++)
163 if (strcmp(*argv, p->c_name) == 0)
164 break;
40a42b7f
TF
165 if (p->c_name == 0 && setaddr)
166 p++; /* got src, do dst */
0fd5cf4f
MK
167 if (p->c_func) {
168 if (p->c_parameter == NEXTARG) {
169 (*p->c_func)(argv[1]);
170 argc--, argv++;
171 } else
172 (*p->c_func)(*argv, p->c_parameter);
173 }
b3eab9f9
SL
174 argc--, argv++;
175 }
62e9bc4a 176 if ((setmask || setaddr) && (af == AF_INET)){
0fd5cf4f
MK
177 /*
178 * If setting the address and not the mask,
179 * clear any existing mask and the kernel will then
180 * assign the default. If setting both,
181 * set the mask first, so the address will be
182 * interpreted correctly.
183 */
0fd5cf4f
MK
184 ifr.ifr_addr = *(struct sockaddr *)&netmask;
185 if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0)
186 Perror("ioctl (SIOCSIFNETMASK)");
187 }
62e9bc4a
KS
188 if (setipdst && af==AF_NS) {
189 struct nsip_req rq;
190 int size = sizeof(rq);
191
192 rq.rq_ns = *(struct sockaddr *) &sin;
193 rq.rq_ip = *(struct sockaddr *) &ipdst;
194
195 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
196 Perror("Encapsulation Routing");
197 setaddr = 0;
198 }
dea973a0 199 if (setaddr) {
dea973a0
MK
200 ifr.ifr_addr = *(struct sockaddr *) &sin;
201 if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0)
202 Perror("ioctl (SIOCSIFADDR)");
203 }
0fd5cf4f 204 if (setbroadaddr) {
0fd5cf4f
MK
205 ifr.ifr_addr = *(struct sockaddr *)&broadaddr;
206 if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0)
207 Perror("ioctl (SIOCSIFBRDADDR)");
208 }
b3eab9f9
SL
209 exit(0);
210}
211
212/*ARGSUSED*/
213setifaddr(addr, param)
214 char *addr;
62e9bc4a 215 short param;
b3eab9f9 216{
dea973a0
MK
217 /*
218 * Delay the ioctl to set the interface addr until flags are all set.
219 * The address interpretation may depend on the flags,
220 * and the flags may change when the address is set.
a9575a9a 221 */
dea973a0 222 setaddr++;
62e9bc4a 223 (*afp->af_getaddr)(addr, &sin);
b3eab9f9
SL
224}
225
0fd5cf4f
MK
226setifnetmask(addr)
227 char *addr;
228{
62e9bc4a 229 in_getaddr(addr, &netmask);
0fd5cf4f
MK
230 setmask++;
231}
232
233setifbroadaddr(addr)
234 char *addr;
235{
62e9bc4a 236 (*afp->af_getaddr)(addr, &broadaddr);
0fd5cf4f
MK
237 setbroadaddr++;
238}
239
62e9bc4a
KS
240setifipdst(addr)
241 char *addr;
242{
243 in_getaddr(addr, &ipdst);
244 setipdst++;
245}
246
40a42b7f
TF
247/*ARGSUSED*/
248setifdstaddr(addr, param)
249 char *addr;
250 int param;
251{
252
62e9bc4a 253 (*afp->af_getaddr)(addr, &ifr.ifr_addr);
40a42b7f
TF
254 if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0)
255 Perror("ioctl (SIOCSIFDSTADDR)");
256}
257
2c4ef00e
SL
258setifflags(vname, value)
259 char *vname;
62e9bc4a 260 short value;
b3eab9f9 261{
62e9bc4a
KS
262 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
263 Perror("ioctl (SIOCGIFFLAGS)");
264 exit(1);
265 }
266 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
267 flags = ifr.ifr_flags;
b3eab9f9
SL
268
269 if (value < 0) {
270 value = -value;
0fd5cf4f 271 flags &= ~value;
b3eab9f9 272 } else
0fd5cf4f 273 flags |= value;
0fd5cf4f 274 ifr.ifr_flags = flags;
b3eab9f9 275 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
2c4ef00e 276 Perror(vname);
b3eab9f9
SL
277}
278
f5f09b9d
MK
279setifmetric(val)
280 char *val;
281{
282 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
283 ifr.ifr_metric = atoi(val);
284 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
285 perror("ioctl (set metric)");
286}
287
288#define IFFBITS \
289"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
290"
291
62e9bc4a
KS
292/*
293 * Print the status of the interface. If an address family was
294 * specified, show it and it only; otherwise, show them all.
295 */
b3eab9f9 296status()
62e9bc4a
KS
297{
298 register struct afswtch *p = afp;
299 short af = ifr.ifr_addr.sa_family;
300
f5f09b9d
MK
301 printf("%s: ", name);
302 printb("flags", flags, IFFBITS);
303 if (metric)
304 printf(" metric %d", metric);
305 putchar('\n');
62e9bc4a
KS
306 if ((p = afp) != NULL) {
307 (*p->af_status)();
308 return;
309 }
310 for (p = afs; p->af_name; p++) {
311 ifr.ifr_addr.sa_family = p->af_af;
312 (*p->af_status)();
313 }
314}
315
62e9bc4a 316in_status()
b3eab9f9
SL
317{
318 struct sockaddr_in *sin;
62e9bc4a 319 char *inet_ntoa();
b3eab9f9 320
0fd5cf4f
MK
321 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
322 if (errno == EADDRNOTAVAIL)
323 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
324 else
325 Perror("ioctl (SIOCGIFADDR)");
326 }
62e9bc4a 327 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
b3eab9f9 328 sin = (struct sockaddr_in *)&ifr.ifr_addr;
5868d993 329 printf("\tinet %s ", inet_ntoa(sin->sin_addr));
40a42b7f 330 if (flags & IFF_POINTOPOINT) {
0fd5cf4f
MK
331 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
332 if (errno == EADDRNOTAVAIL)
333 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
334 else
335 Perror("ioctl (SIOCGIFDSTADDR)");
336 }
62e9bc4a 337 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
40a42b7f
TF
338 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
339 printf("--> %s ", inet_ntoa(sin->sin_addr));
340 }
0fd5cf4f 341 printf("netmask %x ", ntohl(netmask.sin_addr.s_addr));
0fd5cf4f 342 if (flags & IFF_BROADCAST) {
0fd5cf4f
MK
343 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
344 if (errno == EADDRNOTAVAIL)
345 return;
346 Perror("ioctl (SIOCGIFADDR)");
347 }
62e9bc4a 348 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
0fd5cf4f 349 sin = (struct sockaddr_in *)&ifr.ifr_addr;
f5f09b9d 350 printf("broadcast %s", inet_ntoa(sin->sin_addr));
0fd5cf4f 351 }
f5f09b9d 352 putchar('\n');
b3eab9f9
SL
353}
354
62e9bc4a
KS
355
356xns_status()
357{
358 struct sockaddr_ns *sns;
62e9bc4a
KS
359
360 close(s);
361 s = socket(AF_NS, SOCK_DGRAM, 0);
362 if (s < 0) {
63f46c0f
KS
363 if (errno == EAFNOSUPPORT)
364 return;
62e9bc4a
KS
365 perror("ifconfig: socket");
366 exit(1);
367 }
368 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
63f46c0f 369 if (errno == EADDRNOTAVAIL || errno==EAFNOSUPPORT)
62e9bc4a
KS
370 return;
371 Perror("ioctl (SIOCGIFADDR)");
372 }
373 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
374 sns = (struct sockaddr_ns *)&ifr.ifr_addr;
f5f09b9d 375 printf("\tns %s ", ns_ntoa(sns->sns_addr));
90a22cbc
KS
376 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
377 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
378 if (errno == EADDRNOTAVAIL)
379 bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
380 else
381 Perror("ioctl (SIOCGIFDSTADDR)");
382 }
383 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
384 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
385 printf("--> %s ", ns_ntoa(sns->sns_addr));
386 }
62e9bc4a
KS
387 putchar('\n');
388}
389
b3eab9f9
SL
390Perror(cmd)
391 char *cmd;
392{
393 extern int errno;
394
395 fprintf(stderr, "ifconfig: ");
396 switch (errno) {
397
398 case ENXIO:
62e9bc4a 399 fprintf(stderr, "%s: no such interface\n", cmd);
b3eab9f9
SL
400 break;
401
402 case EPERM:
9f1b5d96 403 fprintf(stderr, "%s: permission denied\n", cmd);
b3eab9f9
SL
404 break;
405
406 default:
407 perror(cmd);
408 }
409 exit(1);
410}
411
412struct in_addr inet_makeaddr();
413
62e9bc4a 414in_getaddr(s, saddr)
b3eab9f9 415 char *s;
62e9bc4a 416 struct sockaddr *saddr;
b3eab9f9 417{
62e9bc4a 418 register struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
b3eab9f9
SL
419 struct hostent *hp;
420 struct netent *np;
421 int val;
422
0fd5cf4f
MK
423 sin->sin_family = AF_INET;
424 val = inet_addr(s);
425 if (val != -1) {
426 sin->sin_addr.s_addr = val;
427 return;
428 }
b3eab9f9
SL
429 hp = gethostbyname(s);
430 if (hp) {
431 sin->sin_family = hp->h_addrtype;
432 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
433 return;
434 }
435 np = getnetbyname(s);
436 if (np) {
437 sin->sin_family = np->n_addrtype;
438 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
439 return;
440 }
b3eab9f9
SL
441 fprintf(stderr, "%s: bad value\n", s);
442 exit(1);
443}
444
445/*
446 * Print a value a la the %b format of the kernel's printf
447 */
448printb(s, v, bits)
449 char *s;
450 register char *bits;
451 register unsigned short v;
452{
453 register int i, any = 0;
454 register char c;
455
456 if (bits && *bits == 8)
457 printf("%s=%o", s, v);
458 else
459 printf("%s=%x", s, v);
460 bits++;
461 if (bits) {
462 putchar('<');
463 while (i = *bits++) {
464 if (v & (1 << (i-1))) {
465 if (any)
466 putchar(',');
467 any = 1;
468 for (; (c = *bits) > 32; bits++)
469 putchar(c);
470 } else
471 for (; *bits > 32; bits++)
472 ;
473 }
474 putchar('>');
475 }
476}
62e9bc4a 477
62e9bc4a
KS
478xns_getaddr(addr, saddr)
479char *addr;
480struct sockaddr *saddr;
481{
90a22cbc
KS
482 struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr;
483 struct ns_addr ns_addr();
62e9bc4a 484 sns->sns_family = AF_NS;
90a22cbc 485 sns->sns_addr = ns_addr(addr);
62e9bc4a 486}