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