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