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