ifconfig.c revision 1.50.2.2 1 /* $NetBSD: ifconfig.c,v 1.50.2.2 1999/06/18 17:42:19 perry Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1983, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by the University of
55 * California, Berkeley and its contributors.
56 * 4. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission.
59 *
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 * SUCH DAMAGE.
71 */
72
73 #include <sys/cdefs.h>
74 #ifndef lint
75 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
76 The Regents of the University of California. All rights reserved.\n");
77 #endif /* not lint */
78
79 #ifndef lint
80 #if 0
81 static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
82 #else
83 __RCSID("$NetBSD: ifconfig.c,v 1.50.2.2 1999/06/18 17:42:19 perry Exp $");
84 #endif
85 #endif /* not lint */
86
87 #include <sys/param.h>
88 #include <sys/socket.h>
89 #include <sys/ioctl.h>
90
91 #include <net/if.h>
92 #include <net/if_dl.h>
93 #include <net/if_media.h>
94 #include <netinet/in.h>
95 #include <arpa/inet.h>
96
97 #include <netatalk/at.h>
98
99 #define NSIP
100 #include <netns/ns.h>
101 #include <netns/ns_if.h>
102 #include <netdb.h>
103
104 #define EON
105 #include <netiso/iso.h>
106 #include <netiso/iso_var.h>
107 #include <sys/protosw.h>
108
109 #include <ctype.h>
110 #include <err.h>
111 #include <errno.h>
112 #include <stddef.h>
113 #include <stdio.h>
114 #include <stdlib.h>
115 #include <string.h>
116 #include <unistd.h>
117
118 struct ifreq ifr, ridreq;
119 struct ifaliasreq addreq __attribute__((aligned(4)));
120 struct iso_ifreq iso_ridreq;
121 struct iso_aliasreq iso_addreq;
122 struct sockaddr_in netmask;
123 struct netrange at_nr; /* AppleTalk net range */
124
125 char name[30];
126 int flags, metric, mtu, setaddr, setipdst, doalias;
127 int clearaddr, s;
128 int newaddr = -1;
129 int nsellength = 1;
130 int af;
131 int Aflag, aflag, dflag, mflag, lflag, uflag;
132 int reset_if_flags;
133
134 void notealias __P((char *, int));
135 void notrailers __P((char *, int));
136 void setifaddr __P((char *, int));
137 void setifdstaddr __P((char *, int));
138 void setifflags __P((char *, int));
139 void setifbroadaddr __P((char *, int));
140 void setifipdst __P((char *, int));
141 void setifmetric __P((char *, int));
142 void setifmtu __P((char *, int));
143 void setifnetmask __P((char *, int));
144 void setnsellength __P((char *, int));
145 void setsnpaoffset __P((char *, int));
146 void setatrange __P((char *, int));
147 void setatphase __P((char *, int));
148 void checkatrange __P ((struct sockaddr_at *));
149 void setmedia __P((char *, int));
150 void setmediaopt __P((char *, int));
151 void unsetmediaopt __P((char *, int));
152 void setmediainst __P((char *, int));
153 void fixnsel __P((struct sockaddr_iso *));
154 int main __P((int, char *[]));
155
156 /*
157 * Media stuff. Whenever a media command is first performed, the
158 * currently select media is grabbed for this interface. If `media'
159 * is given, the current media word is modifed. `mediaopt' commands
160 * only modify the set and clear words. They then operate on the
161 * current media word later.
162 */
163 int media_current;
164 int mediaopt_set;
165 int mediaopt_clear;
166
167 int actions; /* Actions performed */
168
169 #define A_MEDIA 0x0001 /* media command */
170 #define A_MEDIAOPTSET 0x0002 /* mediaopt command */
171 #define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */
172 #define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR)
173 #define A_MEDIAINST 0x0008 /* instance or inst command */
174
175 #define NEXTARG 0xffffff
176
177 struct cmd {
178 char *c_name;
179 int c_parameter; /* NEXTARG means next argv */
180 int c_action; /* defered action */
181 void (*c_func) __P((char *, int));
182 } cmds[] = {
183 { "up", IFF_UP, 0, setifflags } ,
184 { "down", -IFF_UP, 0, setifflags },
185 { "trailers", -1, 0, notrailers },
186 { "-trailers", 1, 0, notrailers },
187 { "arp", -IFF_NOARP, 0, setifflags },
188 { "-arp", IFF_NOARP, 0, setifflags },
189 { "debug", IFF_DEBUG, 0, setifflags },
190 { "-debug", -IFF_DEBUG, 0, setifflags },
191 { "alias", IFF_UP, 0, notealias },
192 { "-alias", -IFF_UP, 0, notealias },
193 { "delete", -IFF_UP, 0, notealias },
194 #ifdef notdef
195 #define EN_SWABIPS 0x1000
196 { "swabips", EN_SWABIPS, 0, setifflags },
197 { "-swabips", -EN_SWABIPS, 0, setifflags },
198 #endif
199 { "netmask", NEXTARG, 0, setifnetmask },
200 { "metric", NEXTARG, 0, setifmetric },
201 { "mtu", NEXTARG, 0, setifmtu },
202 { "broadcast", NEXTARG, 0, setifbroadaddr },
203 { "ipdst", NEXTARG, 0, setifipdst },
204 #ifndef INET_ONLY
205 { "range", NEXTARG, 0, setatrange },
206 { "phase", NEXTARG, 0, setatphase },
207 { "snpaoffset", NEXTARG, 0, setsnpaoffset },
208 { "nsellength", NEXTARG, 0, setnsellength },
209 #endif /* INET_ONLY */
210 { "link0", IFF_LINK0, 0, setifflags } ,
211 { "-link0", -IFF_LINK0, 0, setifflags } ,
212 { "link1", IFF_LINK1, 0, setifflags } ,
213 { "-link1", -IFF_LINK1, 0, setifflags } ,
214 { "link2", IFF_LINK2, 0, setifflags } ,
215 { "-link2", -IFF_LINK2, 0, setifflags } ,
216 { "media", NEXTARG, A_MEDIA, setmedia },
217 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt },
218 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt },
219 { "instance", NEXTARG, A_MEDIAINST, setmediainst },
220 { "inst", NEXTARG, A_MEDIAINST, setmediainst },
221 { 0, 0, 0, setifaddr },
222 { 0, 0, 0, setifdstaddr },
223 };
224
225 void adjust_nsellength __P((void));
226 int getinfo __P((struct ifreq *));
227 void getsock __P((int));
228 void printall __P((void));
229 void printalias __P((const char *));
230 void printb __P((char *, unsigned short, char *));
231 void status __P((const u_int8_t *, int));
232 void usage __P((void));
233
234 const char *get_media_type_string __P((int));
235 const char *get_media_subtype_string __P((int));
236 int get_media_subtype __P((int, const char *));
237 int get_media_options __P((int, const char *));
238 int lookup_media_word __P((struct ifmedia_description *, int,
239 const char *));
240 void print_media_word __P((int, int, int));
241 void process_media_commands __P((void));
242 void init_current_media __P((void));
243
244 /*
245 * XNS support liberally adapted from code written at the University of
246 * Maryland principally by James O'Toole and Chris Torek.
247 */
248 void in_alias __P((struct ifreq *));
249 void in_status __P((int));
250 void in_getaddr __P((char *, int));
251 void at_status __P((int));
252 void at_getaddr __P((char *, int));
253 void xns_status __P((int));
254 void xns_getaddr __P((char *, int));
255 void iso_status __P((int));
256 void iso_getaddr __P((char *, int));
257
258 /* Known address families */
259 struct afswtch {
260 char *af_name;
261 short af_af;
262 void (*af_status) __P((int));
263 void (*af_getaddr) __P((char *, int));
264 u_long af_difaddr;
265 u_long af_aifaddr;
266 caddr_t af_ridreq;
267 caddr_t af_addreq;
268 } afs[] = {
269 #define C(x) ((caddr_t) &x)
270 { "inet", AF_INET, in_status, in_getaddr,
271 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
272 #ifndef INET_ONLY /* small version, for boot media */
273 { "atalk", AF_APPLETALK, at_status, at_getaddr,
274 SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) },
275 { "ns", AF_NS, xns_status, xns_getaddr,
276 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
277 { "iso", AF_ISO, iso_status, iso_getaddr,
278 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) },
279 #endif /* INET_ONLY */
280 { 0, 0, 0, 0 }
281 };
282
283 struct afswtch *afp; /*the address family being set or asked about*/
284
285 struct afswtch *lookup_af __P((const char *));
286
287 int
288 main(argc, argv)
289 int argc;
290 char *argv[];
291 {
292 int ch;
293
294 /* Parse command-line options */
295 aflag = mflag = 0;
296 while ((ch = getopt(argc, argv, "Aadlmu")) != -1) {
297 switch (ch) {
298 case 'A':
299 Aflag = 1;
300 break;
301
302 case 'a':
303 aflag = 1;
304 break;
305
306 case 'd':
307 dflag = 1;
308 break;
309
310 case 'l':
311 lflag = 1;
312 break;
313
314 case 'm':
315 mflag = 1;
316 break;
317
318 case 'u':
319 uflag = 1;
320 break;
321
322 default:
323 usage();
324 /* NOTREACHED */
325 }
326 }
327 argc -= optind;
328 argv += optind;
329
330 /*
331 * -l means "list all interfaces", and is mutally exclusive with
332 * all other flags/commands.
333 *
334 * -a means "print status of all interfaces".
335 */
336 if (lflag && (aflag || mflag || argc))
337 usage();
338 if (aflag || lflag) {
339 if (argc > 1)
340 usage();
341 else if (argc == 1) {
342 afp = lookup_af(argv[0]);
343 if (afp == NULL)
344 usage();
345 }
346 if (afp)
347 af = ifr.ifr_addr.sa_family = afp->af_af;
348 else
349 af = ifr.ifr_addr.sa_family = afs[0].af_af;
350 printall();
351 exit(0);
352 }
353
354 /* Make sure there's an interface name. */
355 if (argc < 1)
356 usage();
357 (void) strncpy(name, argv[0], sizeof(name));
358 argc--; argv++;
359
360 /* Check for address family. */
361 afp = NULL;
362 if (argc > 0) {
363 afp = lookup_af(argv[0]);
364 if (afp != NULL) {
365 argv++;
366 argc--;
367 }
368 }
369
370 /* Initialize af, just for use in getinfo(). */
371 if (afp == NULL)
372 af = afs->af_af;
373 else
374 af = afp->af_af;
375
376 /* Get information about the interface. */
377 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
378 if (getinfo(&ifr) < 0)
379 exit(1);
380
381 /* No more arguments means interface status. */
382 if (argc == 0) {
383 status(NULL, 0);
384 exit(0);
385 }
386
387 /* The following operations assume inet family as the default. */
388 if (afp == NULL)
389 afp = afs;
390 af = ifr.ifr_addr.sa_family = afp->af_af;
391
392 /* Process commands. */
393 while (argc > 0) {
394 struct cmd *p;
395
396 for (p = cmds; p->c_name; p++)
397 if (strcmp(argv[0], p->c_name) == 0)
398 break;
399 if (p->c_name == 0 && setaddr)
400 p++; /* got src, do dst */
401 if (p->c_func) {
402 if (p->c_parameter == NEXTARG) {
403 if (argc < 2)
404 errx(1, "'%s' requires argument",
405 p->c_name);
406 (*p->c_func)(argv[1], 0);
407 argc--, argv++;
408 } else
409 (*p->c_func)(argv[0], p->c_parameter);
410 actions |= p->c_action;
411 }
412 argc--, argv++;
413 }
414
415 /* Process any media commands that may have been issued. */
416 process_media_commands();
417
418 #ifndef INET_ONLY
419
420 if (af == AF_ISO)
421 adjust_nsellength();
422
423 if (af == AF_APPLETALK)
424 checkatrange((struct sockaddr_at *) &addreq.ifra_addr);
425
426 if (setipdst && af==AF_NS) {
427 struct nsip_req rq;
428 int size = sizeof(rq);
429
430 rq.rq_ns = addreq.ifra_addr;
431 rq.rq_ip = addreq.ifra_dstaddr;
432
433 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
434 warn("encapsulation routing");
435 }
436
437 #endif /* INET_ONLY */
438
439 if (clearaddr) {
440 int ret;
441 (void) strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
442 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) {
443 if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
444 /* means no previous address for interface */
445 } else
446 warn("SIOCDIFADDR");
447 }
448 }
449 if (newaddr > 0) {
450 (void) strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
451 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
452 warn("SIOCAIFADDR");
453 }
454 if (reset_if_flags && ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
455 err(1, "SIOCSIFFLAGS");
456 exit(0);
457 }
458
459 struct afswtch *
460 lookup_af(cp)
461 const char *cp;
462 {
463 struct afswtch *a;
464
465 for (a = afs; a->af_name != NULL; a++)
466 if (strcmp(a->af_name, cp) == 0)
467 return (a);
468 return (NULL);
469 }
470
471 void
472 getsock(naf)
473 int naf;
474 {
475 static int oaf = -1;
476
477 if (oaf == naf)
478 return;
479 if (oaf != -1)
480 close(s);
481 s = socket(naf, SOCK_DGRAM, 0);
482 if (s < 0)
483 oaf = -1;
484 else
485 oaf = naf;
486 }
487
488 int
489 getinfo(ifr)
490 struct ifreq *ifr;
491 {
492
493 getsock(af);
494 if (s < 0)
495 err(1, "socket");
496 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) {
497 warn("SIOCGIFFLAGS %s", ifr->ifr_name);
498 return (-1);
499 }
500 flags = ifr->ifr_flags;
501 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) {
502 warn("SIOCGIFMETRIC %s", ifr->ifr_name);
503 metric = 0;
504 } else
505 metric = ifr->ifr_metric;
506 if (ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0)
507 mtu = 0;
508 else
509 mtu = ifr->ifr_mtu;
510 return (0);
511 }
512
513 void
514 printalias(iname)
515 const char *iname;
516 {
517 char inbuf[8192];
518 struct ifconf ifc;
519 struct ifreq *ifr;
520 int i;
521
522 ifc.ifc_len = sizeof(inbuf);
523 ifc.ifc_buf = inbuf;
524 getsock(af);
525 if (s < 0)
526 err(1, "socket");
527 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
528 err(1, "SIOCGIFCONF");
529 ifr = ifc.ifc_req;
530 for (i = 0; i < ifc.ifc_len; ) {
531 ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
532 i += sizeof(ifr->ifr_name) +
533 (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
534 ? ifr->ifr_addr.sa_len
535 : sizeof(struct sockaddr));
536 if (!strncmp(iname, ifr->ifr_name, sizeof(ifr->ifr_name))) {
537 if (ifr->ifr_addr.sa_family == AF_INET)
538 in_alias(ifr);
539 continue;
540 }
541 }
542 }
543
544 void
545 printall()
546 {
547 char inbuf[8192];
548 const struct sockaddr_dl *sdl = NULL;
549 struct ifconf ifc;
550 struct ifreq ifreq, *ifr;
551 int i, idx;
552
553 ifc.ifc_len = sizeof(inbuf);
554 ifc.ifc_buf = inbuf;
555 getsock(af);
556 if (s < 0)
557 err(1, "socket");
558 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
559 err(1, "SIOCGIFCONF");
560 ifr = ifc.ifc_req;
561 ifreq.ifr_name[0] = '\0';
562 for (i = 0, idx = 0; i < ifc.ifc_len; ) {
563 ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
564 i += sizeof(ifr->ifr_name) +
565 (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
566 ? ifr->ifr_addr.sa_len
567 : sizeof(struct sockaddr));
568 if (ifr->ifr_addr.sa_family == AF_LINK)
569 sdl = (const struct sockaddr_dl *) &ifr->ifr_addr;
570 if (!strncmp(ifreq.ifr_name, ifr->ifr_name,
571 sizeof(ifr->ifr_name))) {
572 if (Aflag && ifr->ifr_addr.sa_family == AF_INET)
573 in_alias(ifr);
574 continue;
575 }
576 (void) strncpy(name, ifr->ifr_name, sizeof(ifr->ifr_name));
577 ifreq = *ifr;
578
579 if (getinfo(&ifreq) < 0)
580 continue;
581 if (dflag && (flags & IFF_UP) != 0)
582 continue;
583 if (uflag && (flags & IFF_UP) == 0)
584 continue;
585
586 idx++;
587 /*
588 * Are we just listing the interfaces?
589 */
590 if (lflag) {
591 if (idx > 1)
592 putchar(' ');
593 fputs(name, stdout);
594 continue;
595 }
596
597 if (sdl == NULL) {
598 status(NULL, 0);
599 } else {
600 status(LLADDR(sdl), sdl->sdl_alen);
601 sdl = NULL;
602 }
603 }
604 if (lflag)
605 putchar('\n');
606 }
607
608 #define RIDADDR 0
609 #define ADDR 1
610 #define MASK 2
611 #define DSTADDR 3
612
613 /*ARGSUSED*/
614 void
615 setifaddr(addr, param)
616 char *addr;
617 int param;
618 {
619 /*
620 * Delay the ioctl to set the interface addr until flags are all set.
621 * The address interpretation may depend on the flags,
622 * and the flags may change when the address is set.
623 */
624 setaddr++;
625 if (newaddr == -1)
626 newaddr = 1;
627 if (doalias == 0)
628 clearaddr = 1;
629 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
630 }
631
632 void
633 setifnetmask(addr, d)
634 char *addr;
635 int d;
636 {
637 (*afp->af_getaddr)(addr, MASK);
638 }
639
640 void
641 setifbroadaddr(addr, d)
642 char *addr;
643 int d;
644 {
645 (*afp->af_getaddr)(addr, DSTADDR);
646 }
647
648 void
649 setifipdst(addr, d)
650 char *addr;
651 int d;
652 {
653 in_getaddr(addr, DSTADDR);
654 setipdst++;
655 clearaddr = 0;
656 newaddr = 0;
657 }
658
659 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
660 /*ARGSUSED*/
661 void
662 notealias(addr, param)
663 char *addr;
664 int param;
665 {
666 if (setaddr && doalias == 0 && param < 0)
667 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq),
668 rqtosa(af_addreq)->sa_len);
669 doalias = param;
670 if (param < 0) {
671 clearaddr = 1;
672 newaddr = 0;
673 } else
674 clearaddr = 0;
675 }
676
677 /*ARGSUSED*/
678 void
679 notrailers(vname, value)
680 char *vname;
681 int value;
682 {
683 puts("Note: trailers are no longer sent, but always received");
684 }
685
686 /*ARGSUSED*/
687 void
688 setifdstaddr(addr, param)
689 char *addr;
690 int param;
691 {
692 (*afp->af_getaddr)(addr, DSTADDR);
693 }
694
695 void
696 setifflags(vname, value)
697 char *vname;
698 int value;
699 {
700 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
701 err(1, "SIOCGIFFLAGS");
702 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
703 flags = ifr.ifr_flags;
704
705 if (value < 0) {
706 value = -value;
707 flags &= ~value;
708 } else
709 flags |= value;
710 ifr.ifr_flags = flags;
711 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
712 err(1, "SIOCSIFFLAGS");
713
714 reset_if_flags = 1;
715 }
716
717 void
718 setifmetric(val, d)
719 char *val;
720 int d;
721 {
722 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
723 ifr.ifr_metric = atoi(val);
724 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
725 warn("SIOCSIFMETRIC");
726 }
727
728 void
729 setifmtu(val, d)
730 char *val;
731 int d;
732 {
733 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
734 ifr.ifr_mtu = atoi(val);
735 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
736 warn("SIOCSIFMTU");
737 }
738
739 void
740 init_current_media()
741 {
742 struct ifmediareq ifmr;
743
744 /*
745 * If we have not yet done so, grab the currently-selected
746 * media.
747 */
748 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) {
749 (void) memset(&ifmr, 0, sizeof(ifmr));
750 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
751
752 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
753 /*
754 * If we get E2BIG, the kernel is telling us
755 * that there are more, so we can ignore it.
756 */
757 if (errno != E2BIG)
758 err(1, "SGIOCGIFMEDIA");
759 }
760
761 media_current = ifmr.ifm_current;
762 }
763
764 /* Sanity. */
765 if (IFM_TYPE(media_current) == 0)
766 errx(1, "%s: no link type?", name);
767 }
768
769 void
770 process_media_commands()
771 {
772
773 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) {
774 /* Nothing to do. */
775 return;
776 }
777
778 /*
779 * Media already set up, and commands sanity-checked. Set/clear
780 * any options, and we're ready to go.
781 */
782 media_current |= mediaopt_set;
783 media_current &= ~mediaopt_clear;
784
785 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
786 ifr.ifr_media = media_current;
787
788 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
789 err(1, "SIOCSIFMEDIA");
790 }
791
792 void
793 setmedia(val, d)
794 char *val;
795 int d;
796 {
797 int type, subtype, inst;
798
799 init_current_media();
800
801 /* Only one media command may be given. */
802 if (actions & A_MEDIA)
803 errx(1, "only one `media' command may be issued");
804
805 /* Must not come after mediaopt commands */
806 if (actions & A_MEDIAOPT)
807 errx(1, "may not issue `media' after `mediaopt' commands");
808
809 /*
810 * No need to check if `instance' has been issued; setmediainst()
811 * craps out if `media' has not been specified.
812 */
813
814 type = IFM_TYPE(media_current);
815 inst = IFM_INST(media_current);
816
817 /* Look up the subtype. */
818 subtype = get_media_subtype(type, val);
819
820 /* Build the new current media word. */
821 media_current = IFM_MAKEWORD(type, subtype, 0, inst);
822
823 /* Media will be set after other processing is complete. */
824 }
825
826 void
827 setmediaopt(val, d)
828 char *val;
829 int d;
830 {
831
832 init_current_media();
833
834 /* Can only issue `mediaopt' once. */
835 if (actions & A_MEDIAOPTSET)
836 errx(1, "only one `mediaopt' command may be issued");
837
838 /* Can't issue `mediaopt' if `instance' has already been issued. */
839 if (actions & A_MEDIAINST)
840 errx(1, "may not issue `mediaopt' after `instance'");
841
842 mediaopt_set = get_media_options(IFM_TYPE(media_current), val);
843
844 /* Media will be set after other processing is complete. */
845 }
846
847 void
848 unsetmediaopt(val, d)
849 char *val;
850 int d;
851 {
852
853 init_current_media();
854
855 /* Can only issue `-mediaopt' once. */
856 if (actions & A_MEDIAOPTCLR)
857 errx(1, "only one `-mediaopt' command may be issued");
858
859 /* May not issue `media' and `-mediaopt'. */
860 if (actions & A_MEDIA)
861 errx(1, "may not issue both `media' and `-mediaopt'");
862
863 /*
864 * No need to check for A_MEDIAINST, since the test for A_MEDIA
865 * implicitly checks for A_MEDIAINST.
866 */
867
868 mediaopt_clear = get_media_options(IFM_TYPE(media_current), val);
869
870 /* Media will be set after other processing is complete. */
871 }
872
873 void
874 setmediainst(val, d)
875 char *val;
876 int d;
877 {
878 int type, subtype, options, inst;
879
880 init_current_media();
881
882 /* Can only issue `instance' once. */
883 if (actions & A_MEDIAINST)
884 errx(1, "only one `instance' command may be issued");
885
886 /* Must have already specified `media' */
887 if ((actions & A_MEDIA) == 0)
888 errx(1, "must specify `media' before `instance'");
889
890 type = IFM_TYPE(media_current);
891 subtype = IFM_SUBTYPE(media_current);
892 options = IFM_OPTIONS(media_current);
893
894 inst = atoi(val);
895 if (inst < 0 || inst > IFM_INST_MAX)
896 errx(1, "invalid media instance: %s", val);
897
898 media_current = IFM_MAKEWORD(type, subtype, options, inst);
899
900 /* Media will be set after other processing is complete. */
901 }
902
903 struct ifmedia_description ifm_type_descriptions[] =
904 IFM_TYPE_DESCRIPTIONS;
905
906 struct ifmedia_description ifm_subtype_descriptions[] =
907 IFM_SUBTYPE_DESCRIPTIONS;
908
909 struct ifmedia_description ifm_option_descriptions[] =
910 IFM_OPTION_DESCRIPTIONS;
911
912 const char *
913 get_media_type_string(mword)
914 int mword;
915 {
916 struct ifmedia_description *desc;
917
918 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL;
919 desc++) {
920 if (IFM_TYPE(mword) == desc->ifmt_word)
921 return (desc->ifmt_string);
922 }
923 return ("<unknown type>");
924 }
925
926 const char *
927 get_media_subtype_string(mword)
928 int mword;
929 {
930 struct ifmedia_description *desc;
931
932 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL;
933 desc++) {
934 if (IFM_TYPE_MATCH(desc->ifmt_word, mword) &&
935 IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword))
936 return (desc->ifmt_string);
937 }
938 return ("<unknown subtype>");
939 }
940
941 int
942 get_media_subtype(type, val)
943 int type;
944 const char *val;
945 {
946 int rval;
947
948 rval = lookup_media_word(ifm_subtype_descriptions, type, val);
949 if (rval == -1)
950 errx(1, "unknown %s media subtype: %s",
951 get_media_type_string(type), val);
952
953 return (rval);
954 }
955
956 int
957 get_media_options(type, val)
958 int type;
959 const char *val;
960 {
961 char *optlist, *str;
962 int option, rval = 0;
963
964 /* We muck with the string, so copy it. */
965 optlist = strdup(val);
966 if (optlist == NULL)
967 err(1, "strdup");
968 str = optlist;
969
970 /*
971 * Look up the options in the user-provided comma-separated list.
972 */
973 for (; (str = strtok(str, ",")) != NULL; str = NULL) {
974 option = lookup_media_word(ifm_option_descriptions, type, str);
975 if (option == -1)
976 errx(1, "unknown %s media option: %s",
977 get_media_type_string(type), str);
978 rval |= option;
979 }
980
981 free(optlist);
982 return (rval);
983 }
984
985 int
986 lookup_media_word(desc, type, val)
987 struct ifmedia_description *desc;
988 int type;
989 const char *val;
990 {
991
992 for (; desc->ifmt_string != NULL; desc++) {
993 if (IFM_TYPE_MATCH(desc->ifmt_word, type) &&
994 strcasecmp(desc->ifmt_string, val) == 0)
995 return (desc->ifmt_word);
996 }
997 return (-1);
998 }
999
1000 void
1001 print_media_word(ifmw, print_type, as_syntax)
1002 int ifmw, print_type, as_syntax;
1003 {
1004 struct ifmedia_description *desc;
1005 int seen_option = 0;
1006
1007 if (print_type)
1008 printf("%s ", get_media_type_string(ifmw));
1009 printf("%s%s", as_syntax ? "media " : "",
1010 get_media_subtype_string(ifmw));
1011
1012 /* Find options. */
1013 for (desc = ifm_option_descriptions; desc->ifmt_string != NULL;
1014 desc++) {
1015 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) &&
1016 (ifmw & desc->ifmt_word) != 0 &&
1017 (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) {
1018 if (seen_option == 0)
1019 printf(" %s", as_syntax ? "mediaopt " : "");
1020 printf("%s%s", seen_option ? "," : "",
1021 desc->ifmt_string);
1022 seen_option |= IFM_OPTIONS(desc->ifmt_word);
1023 }
1024 }
1025 if (IFM_INST(ifmw) != 0)
1026 printf(" instance %d", IFM_INST(ifmw));
1027 }
1028
1029 #define IFFBITS \
1030 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
1031 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
1032
1033 /*
1034 * Print the status of the interface. If an address family was
1035 * specified, show it and it only; otherwise, show them all.
1036 */
1037 void
1038 status(ap, alen)
1039 const u_int8_t *ap;
1040 int alen;
1041 {
1042 struct afswtch *p = afp;
1043 struct ifmediareq ifmr;
1044 int *media_list, i;
1045
1046 printf("%s: ", name);
1047 printb("flags", flags, IFFBITS);
1048 if (metric)
1049 printf(" metric %d", metric);
1050 if (mtu)
1051 printf(" mtu %d", mtu);
1052 putchar('\n');
1053 if (ap && alen > 0) {
1054 printf("\taddress:");
1055 for (i = 0; i < alen; i++, ap++)
1056 printf("%c%02x", i > 0 ? ':' : ' ', *ap);
1057 putchar('\n');
1058 }
1059
1060 (void) memset(&ifmr, 0, sizeof(ifmr));
1061 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
1062
1063 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
1064 /*
1065 * Interface doesn't support SIOC{G,S}IFMEDIA.
1066 */
1067 goto proto_status;
1068 }
1069
1070 if (ifmr.ifm_count == 0) {
1071 warnx("%s: no media types?", name);
1072 goto proto_status;
1073 }
1074
1075 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
1076 if (media_list == NULL)
1077 err(1, "malloc");
1078 ifmr.ifm_ulist = media_list;
1079
1080 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
1081 err(1, "SIOCGIFMEDIA");
1082
1083 printf("\tmedia: ");
1084 print_media_word(ifmr.ifm_current, 1, 0);
1085 if (ifmr.ifm_active != ifmr.ifm_current) {
1086 putchar(' ');
1087 putchar('(');
1088 print_media_word(ifmr.ifm_active, 0, 0);
1089 putchar(')');
1090 }
1091 putchar('\n');
1092
1093 if (ifmr.ifm_status & IFM_AVALID) {
1094 printf("\tstatus: ");
1095 switch (IFM_TYPE(ifmr.ifm_active)) {
1096 case IFM_ETHER:
1097 if (ifmr.ifm_status & IFM_ACTIVE)
1098 printf("active");
1099 else
1100 printf("no carrier");
1101 break;
1102
1103 case IFM_FDDI:
1104 case IFM_TOKEN:
1105 if (ifmr.ifm_status & IFM_ACTIVE)
1106 printf("inserted");
1107 else
1108 printf("no ring");
1109 break;
1110 default:
1111 printf("unknown");
1112 }
1113 putchar('\n');
1114 }
1115
1116 if (mflag) {
1117 int type, printed_type;
1118
1119 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) {
1120 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) {
1121 if (IFM_TYPE(media_list[i]) == type) {
1122 if (printed_type == 0) {
1123 printf("\tsupported %s media:\n",
1124 get_media_type_string(type));
1125 printed_type = 1;
1126 }
1127 printf("\t\t");
1128 print_media_word(media_list[i], 0, 1);
1129 printf("\n");
1130 }
1131 }
1132 }
1133 }
1134
1135 free(media_list);
1136
1137 proto_status:
1138 if ((p = afp) != NULL) {
1139 (*p->af_status)(1);
1140 if (Aflag & !aflag)
1141 printalias(name);
1142 } else for (p = afs; p->af_name; p++) {
1143 ifr.ifr_addr.sa_family = p->af_af;
1144 (*p->af_status)(0);
1145 if (Aflag & !aflag && p->af_af == AF_INET)
1146 printalias(name);
1147 }
1148 }
1149
1150 void
1151 in_alias(creq)
1152 struct ifreq *creq;
1153 {
1154 struct sockaddr_in *sin;
1155
1156 if (lflag)
1157 return;
1158
1159 /* Get the non-alias address for this interface. */
1160 getsock(AF_INET);
1161 if (s < 0) {
1162 if (errno == EPROTONOSUPPORT)
1163 return;
1164 err(1, "socket");
1165 }
1166 (void) memset(&ifr, 0, sizeof(ifr));
1167 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1168 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1169 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1170 return;
1171 } else
1172 warn("SIOCGIFADDR");
1173 }
1174 /* If creq and ifr are the same address, this is not an alias. */
1175 if (memcmp(&ifr.ifr_addr, &creq->ifr_addr,
1176 sizeof(creq->ifr_addr)) == 0)
1177 return;
1178 (void) memset(&addreq, 0, sizeof(addreq));
1179 (void) strncpy(addreq.ifra_name, name, sizeof(addreq.ifra_name));
1180 addreq.ifra_addr = creq->ifr_addr;
1181 if (ioctl(s, SIOCGIFALIAS, (caddr_t)&addreq) < 0) {
1182 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1183 return;
1184 } else
1185 warn("SIOCGIFALIAS");
1186 }
1187
1188 sin = (struct sockaddr_in *)&addreq.ifra_addr;
1189 printf("\tinet alias %s", inet_ntoa(sin->sin_addr));
1190
1191 if (flags & IFF_POINTOPOINT) {
1192 sin = (struct sockaddr_in *)&addreq.ifra_dstaddr;
1193 printf(" -> %s", inet_ntoa(sin->sin_addr));
1194 }
1195
1196 sin = (struct sockaddr_in *)&addreq.ifra_mask;
1197 printf(" netmask 0x%x", ntohl(sin->sin_addr.s_addr));
1198
1199 if (flags & IFF_BROADCAST) {
1200 sin = (struct sockaddr_in *)&addreq.ifra_broadaddr;
1201 printf(" broadcast %s", inet_ntoa(sin->sin_addr));
1202 }
1203 printf("\n");
1204 }
1205
1206 void
1207 in_status(force)
1208 int force;
1209 {
1210 struct sockaddr_in *sin;
1211
1212 getsock(AF_INET);
1213 if (s < 0) {
1214 if (errno == EPROTONOSUPPORT)
1215 return;
1216 err(1, "socket");
1217 }
1218 (void) memset(&ifr, 0, sizeof(ifr));
1219 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1220 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1221 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1222 if (!force)
1223 return;
1224 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1225 } else
1226 warn("SIOCGIFADDR");
1227 }
1228 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1229 sin = (struct sockaddr_in *)&ifr.ifr_addr;
1230 printf("\tinet %s ", inet_ntoa(sin->sin_addr));
1231 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1232 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
1233 if (errno != EADDRNOTAVAIL)
1234 warn("SIOCGIFNETMASK");
1235 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1236 } else
1237 netmask.sin_addr =
1238 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
1239 if (flags & IFF_POINTOPOINT) {
1240 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1241 if (errno == EADDRNOTAVAIL)
1242 (void) memset(&ifr.ifr_addr, 0,
1243 sizeof(ifr.ifr_addr));
1244 else
1245 warn("SIOCGIFDSTADDR");
1246 }
1247 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1248 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
1249 printf("--> %s ", inet_ntoa(sin->sin_addr));
1250 }
1251 printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
1252 if (flags & IFF_BROADCAST) {
1253 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
1254 if (errno == EADDRNOTAVAIL)
1255 (void) memset(&ifr.ifr_addr, 0,
1256 sizeof(ifr.ifr_addr));
1257 else
1258 warn("SIOCGIFBRDADDR");
1259 }
1260 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1261 sin = (struct sockaddr_in *)&ifr.ifr_addr;
1262 if (sin->sin_addr.s_addr != 0)
1263 printf("broadcast %s", inet_ntoa(sin->sin_addr));
1264 }
1265 putchar('\n');
1266 }
1267
1268 #ifndef INET_ONLY
1269
1270 void
1271 at_status(force)
1272 int force;
1273 {
1274 struct sockaddr_at *sat, null_sat;
1275 struct netrange *nr;
1276
1277 getsock(AF_APPLETALK);
1278 if (s < 0) {
1279 if (errno == EPROTONOSUPPORT)
1280 return;
1281 err(1, "socket");
1282 }
1283 (void) memset(&ifr, 0, sizeof(ifr));
1284 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1285 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1286 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1287 if (!force)
1288 return;
1289 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1290 } else
1291 warn("SIOCGIFADDR");
1292 }
1293 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1294 sat = (struct sockaddr_at *)&ifr.ifr_addr;
1295
1296 (void) memset(&null_sat, 0, sizeof(null_sat));
1297
1298 nr = (struct netrange *) &sat->sat_zero;
1299 printf("\tatalk %d.%d range %d-%d phase %d",
1300 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1301 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
1302 if (flags & IFF_POINTOPOINT) {
1303 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1304 if (errno == EADDRNOTAVAIL)
1305 (void) memset(&ifr.ifr_addr, 0,
1306 sizeof(ifr.ifr_addr));
1307 else
1308 warn("SIOCGIFDSTADDR");
1309 }
1310 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1311 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr;
1312 if (!sat)
1313 sat = &null_sat;
1314 printf("--> %d.%d",
1315 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
1316 }
1317 if (flags & IFF_BROADCAST) {
1318 /* note RTAX_BRD overlap with IFF_POINTOPOINT */
1319 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr;
1320 if (sat)
1321 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net),
1322 sat->sat_addr.s_node);
1323 }
1324 putchar('\n');
1325 }
1326
1327 void
1328 xns_status(force)
1329 int force;
1330 {
1331 struct sockaddr_ns *sns;
1332
1333 getsock(AF_NS);
1334 if (s < 0) {
1335 if (errno == EPROTONOSUPPORT)
1336 return;
1337 err(1, "socket");
1338 }
1339 (void) memset(&ifr, 0, sizeof(ifr));
1340 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1341 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1342 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1343 if (!force)
1344 return;
1345 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1346 } else
1347 warn("SIOCGIFADDR");
1348 }
1349 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1350 sns = (struct sockaddr_ns *)&ifr.ifr_addr;
1351 printf("\tns %s ", ns_ntoa(sns->sns_addr));
1352 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
1353 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1354 if (errno == EADDRNOTAVAIL)
1355 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1356 else
1357 warn("SIOCGIFDSTADDR");
1358 }
1359 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1360 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
1361 printf("--> %s ", ns_ntoa(sns->sns_addr));
1362 }
1363 putchar('\n');
1364 }
1365
1366 void
1367 iso_status(force)
1368 int force;
1369 {
1370 struct sockaddr_iso *siso;
1371 struct iso_ifreq ifr;
1372
1373 getsock(AF_ISO);
1374 if (s < 0) {
1375 if (errno == EPROTONOSUPPORT)
1376 return;
1377 err(1, "socket");
1378 }
1379 (void) memset(&ifr, 0, sizeof(ifr));
1380 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1381 if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) {
1382 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1383 if (!force)
1384 return;
1385 (void) memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr));
1386 } else
1387 warn("SIOCGIFADDR_ISO");
1388 }
1389 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1390 siso = &ifr.ifr_Addr;
1391 printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
1392 if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) {
1393 if (errno == EADDRNOTAVAIL)
1394 memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr));
1395 else
1396 warn("SIOCGIFNETMASK_ISO");
1397 } else {
1398 if (siso->siso_len > offsetof(struct sockaddr_iso, siso_addr))
1399 siso->siso_addr.isoa_len = siso->siso_len
1400 - offsetof(struct sockaddr_iso, siso_addr);
1401 printf("\n\t\tnetmask %s ", iso_ntoa(&siso->siso_addr));
1402 }
1403 if (flags & IFF_POINTOPOINT) {
1404 if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) {
1405 if (errno == EADDRNOTAVAIL)
1406 memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr));
1407 else
1408 warn("SIOCGIFDSTADDR_ISO");
1409 }
1410 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1411 siso = &ifr.ifr_Addr;
1412 printf("--> %s ", iso_ntoa(&siso->siso_addr));
1413 }
1414 putchar('\n');
1415 }
1416
1417 #endif /* INET_ONLY */
1418
1419 #define SIN(x) ((struct sockaddr_in *) &(x))
1420 struct sockaddr_in *sintab[] = {
1421 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
1422 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
1423
1424 void
1425 in_getaddr(s, which)
1426 char *s;
1427 int which;
1428 {
1429 struct sockaddr_in *sin = sintab[which];
1430 struct hostent *hp;
1431 struct netent *np;
1432
1433 sin->sin_len = sizeof(*sin);
1434 if (which != MASK)
1435 sin->sin_family = AF_INET;
1436
1437 if (inet_aton(s, &sin->sin_addr) == 0) {
1438 if ((hp = gethostbyname(s)) != NULL)
1439 (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
1440 else if ((np = getnetbyname(s)) != NULL)
1441 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
1442 else
1443 errx(1, "%s: bad value", s);
1444 }
1445 }
1446
1447 /*
1448 * Print a value a la the %b format of the kernel's printf
1449 */
1450 void
1451 printb(s, v, bits)
1452 char *s;
1453 char *bits;
1454 unsigned short v;
1455 {
1456 int i, any = 0;
1457 char c;
1458
1459 if (bits && *bits == 8)
1460 printf("%s=%o", s, v);
1461 else
1462 printf("%s=%x", s, v);
1463 bits++;
1464 if (bits) {
1465 putchar('<');
1466 while ((i = *bits++) != 0) {
1467 if (v & (1 << (i-1))) {
1468 if (any)
1469 putchar(',');
1470 any = 1;
1471 for (; (c = *bits) > 32; bits++)
1472 putchar(c);
1473 } else
1474 for (; *bits > 32; bits++)
1475 ;
1476 }
1477 putchar('>');
1478 }
1479 }
1480
1481 #ifndef INET_ONLY
1482
1483 void
1484 at_getaddr(addr, which)
1485 char *addr;
1486 int which;
1487 {
1488 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr;
1489 u_int net, node;
1490
1491 sat->sat_family = AF_APPLETALK;
1492 sat->sat_len = sizeof(*sat);
1493 if (which == MASK)
1494 errx(1, "AppleTalk does not use netmasks\n");
1495 if (sscanf(addr, "%u.%u", &net, &node) != 2
1496 || net == 0 || net > 0xffff || node == 0 || node > 0xfe)
1497 errx(1, "%s: illegal address", addr);
1498 sat->sat_addr.s_net = htons(net);
1499 sat->sat_addr.s_node = node;
1500 }
1501
1502 void
1503 setatrange(range, d)
1504 char *range;
1505 int d;
1506 {
1507 u_short first = 123, last = 123;
1508
1509 if (sscanf(range, "%hu-%hu", &first, &last) != 2
1510 || first == 0 || first > 0xffff
1511 || last == 0 || last > 0xffff || first > last)
1512 errx(1, "%s: illegal net range: %u-%u", range, first, last);
1513 at_nr.nr_firstnet = htons(first);
1514 at_nr.nr_lastnet = htons(last);
1515 }
1516
1517 void
1518 setatphase(phase, d)
1519 char *phase;
1520 int d;
1521 {
1522 if (!strcmp(phase, "1"))
1523 at_nr.nr_phase = 1;
1524 else if (!strcmp(phase, "2"))
1525 at_nr.nr_phase = 2;
1526 else
1527 errx(1, "%s: illegal phase", phase);
1528 }
1529
1530 void
1531 checkatrange(sat)
1532 struct sockaddr_at *sat;
1533 {
1534 if (at_nr.nr_phase == 0)
1535 at_nr.nr_phase = 2; /* Default phase 2 */
1536 if (at_nr.nr_firstnet == 0)
1537 at_nr.nr_firstnet = /* Default range of one */
1538 at_nr.nr_lastnet = sat->sat_addr.s_net;
1539 printf("\tatalk %d.%d range %d-%d phase %d\n",
1540 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1541 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase);
1542 if ((u_short) ntohs(at_nr.nr_firstnet) >
1543 (u_short) ntohs(sat->sat_addr.s_net)
1544 || (u_short) ntohs(at_nr.nr_lastnet) <
1545 (u_short) ntohs(sat->sat_addr.s_net))
1546 errx(1, "AppleTalk address is not in range");
1547 *((struct netrange *) &sat->sat_zero) = at_nr;
1548 }
1549
1550 #define SNS(x) ((struct sockaddr_ns *) &(x))
1551 struct sockaddr_ns *snstab[] = {
1552 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
1553 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
1554
1555 void
1556 xns_getaddr(addr, which)
1557 char *addr;
1558 int which;
1559 {
1560 struct sockaddr_ns *sns = snstab[which];
1561
1562 sns->sns_family = AF_NS;
1563 sns->sns_len = sizeof(*sns);
1564 sns->sns_addr = ns_addr(addr);
1565 if (which == MASK)
1566 puts("Attempt to set XNS netmask will be ineffectual");
1567 }
1568
1569 #define SISO(x) ((struct sockaddr_iso *) &(x))
1570 struct sockaddr_iso *sisotab[] = {
1571 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr),
1572 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
1573
1574 void
1575 iso_getaddr(addr, which)
1576 char *addr;
1577 int which;
1578 {
1579 struct sockaddr_iso *siso = sisotab[which];
1580 siso->siso_addr = *iso_addr(addr);
1581
1582 if (which == MASK) {
1583 siso->siso_len = TSEL(siso) - (caddr_t)(siso);
1584 siso->siso_nlen = 0;
1585 } else {
1586 siso->siso_len = sizeof(*siso);
1587 siso->siso_family = AF_ISO;
1588 }
1589 }
1590
1591 void
1592 setsnpaoffset(val, d)
1593 char *val;
1594 int d;
1595 {
1596 iso_addreq.ifra_snpaoffset = atoi(val);
1597 }
1598
1599 void
1600 setnsellength(val, d)
1601 char *val;
1602 int d;
1603 {
1604 nsellength = atoi(val);
1605 if (nsellength < 0)
1606 errx(1, "Negative NSEL length is absurd");
1607 if (afp == 0 || afp->af_af != AF_ISO)
1608 errx(1, "Setting NSEL length valid only for iso");
1609 }
1610
1611 void
1612 fixnsel(s)
1613 struct sockaddr_iso *s;
1614 {
1615 if (s->siso_family == 0)
1616 return;
1617 s->siso_tlen = nsellength;
1618 }
1619
1620 void
1621 adjust_nsellength()
1622 {
1623 fixnsel(sisotab[RIDADDR]);
1624 fixnsel(sisotab[ADDR]);
1625 fixnsel(sisotab[DSTADDR]);
1626 }
1627
1628 #endif /* INET_ONLY */
1629
1630 void
1631 usage()
1632 {
1633 fprintf(stderr,
1634 "usage: ifconfig [ -m ] [ -A ] interface\n%s%s%s%s%s%s%s%s%s%s%s%s",
1635 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ] ",
1636 "[ netmask mask ] ]\n",
1637 "\t[ metric n ]\n",
1638 "\t[ mtu n ]\n",
1639 "\t[ arp | -arp ]\n",
1640 "\t[ media mtype ]\n",
1641 "\t[ mediaopt mopts ]\n",
1642 "\t[ -mediaopt mopts ]\n",
1643 "\t[ instance minst ]\n",
1644 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n",
1645 " ifconfig -a [ -A ] [ -m ] [ -d ] [ -u ] [ af ]\n",
1646 " ifconfig -l [ -d ] [ -u ]\n");
1647 exit(1);
1648 }
1649