ifconfig.c revision 1.35 1 /* $NetBSD: ifconfig.c,v 1.35 1997/05/05 06:32:11 thorpej 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.35 1997/05/05 06:32:11 thorpej 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) {
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_metric;
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 (doalias == 0)
539 clearaddr = 1;
540 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
541 }
542
543 void
544 setifnetmask(addr, d)
545 char *addr;
546 int d;
547 {
548 (*afp->af_getaddr)(addr, MASK);
549 }
550
551 void
552 setifbroadaddr(addr, d)
553 char *addr;
554 int d;
555 {
556 (*afp->af_getaddr)(addr, DSTADDR);
557 }
558
559 void
560 setifipdst(addr, d)
561 char *addr;
562 int d;
563 {
564 in_getaddr(addr, DSTADDR);
565 setipdst++;
566 clearaddr = 0;
567 newaddr = 0;
568 }
569
570 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
571 /*ARGSUSED*/
572 void
573 notealias(addr, param)
574 char *addr;
575 int param;
576 {
577 if (setaddr && doalias == 0 && param < 0)
578 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq),
579 rqtosa(af_addreq)->sa_len);
580 doalias = param;
581 if (param < 0) {
582 clearaddr = 1;
583 newaddr = 0;
584 } else
585 clearaddr = 0;
586 }
587
588 /*ARGSUSED*/
589 void
590 notrailers(vname, value)
591 char *vname;
592 int value;
593 {
594 puts("Note: trailers are no longer sent, but always received");
595 }
596
597 /*ARGSUSED*/
598 void
599 setifdstaddr(addr, param)
600 char *addr;
601 int param;
602 {
603 (*afp->af_getaddr)(addr, DSTADDR);
604 }
605
606 void
607 setifflags(vname, value)
608 char *vname;
609 int value;
610 {
611 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
612 err(1, "SIOCGIFFLAGS");
613 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
614 flags = ifr.ifr_flags;
615
616 if (value < 0) {
617 value = -value;
618 flags &= ~value;
619 } else
620 flags |= value;
621 ifr.ifr_flags = flags;
622 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
623 err(1, "SIOCSIFFLAGS");
624 }
625
626 void
627 setifmetric(val, d)
628 char *val;
629 int d;
630 {
631 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
632 ifr.ifr_metric = atoi(val);
633 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
634 warn("SIOCSIFMETRIC");
635 }
636
637 void
638 setifmtu(val, d)
639 char *val;
640 int d;
641 {
642 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
643 ifr.ifr_metric = atoi(val);
644 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
645 warn("SIOCSIFMTU");
646 }
647
648 void
649 setmedia(val, d)
650 char *val;
651 int d;
652 {
653 struct ifmediareq ifmr;
654 int first_type, subtype;
655
656 (void) memset(&ifmr, 0, sizeof(ifmr));
657 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
658
659 ifmr.ifm_count = 1;
660 ifmr.ifm_ulist = &first_type;
661 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
662 /*
663 * If we get E2BIG, the kernel is telling us
664 * that there are more, so we can ignore it.
665 */
666 if (errno != E2BIG)
667 err(1, "SIOCGIFMEDIA");
668 }
669
670 if (ifmr.ifm_count == 0)
671 errx(1, "%s: no media types?", name);
672
673 /*
674 * We are primarily concerned with the top-level type.
675 * However, "current" may be only IFM_NONE, so we just look
676 * for the top-level type in the first "supported type"
677 * entry.
678 *
679 * (I'm assuming that all supported media types for a given
680 * interface will be the same top-level type..)
681 */
682 subtype = get_media_subtype(IFM_TYPE(first_type), val);
683
684 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
685 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
686 IFM_TYPE(first_type) | subtype;
687
688 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
689 err(1, "SIOCSIFMEDIA");
690 }
691
692 void
693 setmediaopt(val, d)
694 char *val;
695 int d;
696 {
697
698 domediaopt(val, 0);
699 }
700
701 void
702 unsetmediaopt(val, d)
703 int d;
704 char *val;
705 {
706
707 domediaopt(val, 1);
708 }
709
710 void
711 domediaopt(val, clear)
712 char *val;
713 int clear;
714 {
715 struct ifmediareq ifmr;
716 int *mwords, options;
717
718 (void) memset(&ifmr, 0, sizeof(ifmr));
719 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
720
721 /*
722 * We must go through the motions of reading all
723 * supported media because we need to know both
724 * the current media type and the top-level type.
725 */
726
727 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
728 err(1, "SIOCGIFMEDIA");
729
730 if (ifmr.ifm_count == 0)
731 errx(1, "%s: no media types?", name);
732
733 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
734 if (mwords == NULL)
735 err(1, "malloc");
736
737 ifmr.ifm_ulist = mwords;
738 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
739 err(1, "SIOCGIFMEDIA");
740
741 options = get_media_options(IFM_TYPE(mwords[0]), val);
742
743 free(mwords);
744
745 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
746 ifr.ifr_media = ifmr.ifm_current;
747 if (clear)
748 ifr.ifr_media &= ~options;
749 else
750 ifr.ifr_media |= options;
751
752 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
753 err(1, "SIOCSIFMEDIA");
754 }
755
756 /**********************************************************************
757 * A good chunk of this is duplicated from sys/net/ifmedia.c
758 **********************************************************************/
759
760 struct ifmedia_description ifm_type_descriptions[] =
761 IFM_TYPE_DESCRIPTIONS;
762
763 struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
764 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
765
766 struct ifmedia_description ifm_subtype_ethernet_aliases[] =
767 IFM_SUBTYPE_ETHERNET_ALIASES;
768
769 struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
770 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
771
772 struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
773 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
774
775 struct ifmedia_description ifm_subtype_tokenring_aliases[] =
776 IFM_SUBTYPE_TOKENRING_ALIASES;
777
778 struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
779 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
780
781 struct ifmedia_description ifm_subtype_fddi_descriptions[] =
782 IFM_SUBTYPE_FDDI_DESCRIPTIONS;
783
784 struct ifmedia_description ifm_subtype_fddi_aliases[] =
785 IFM_SUBTYPE_FDDI_ALIASES;
786
787 struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
788 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
789
790 struct ifmedia_description ifm_subtype_shared_descriptions[] =
791 IFM_SUBTYPE_SHARED_DESCRIPTIONS;
792
793 struct ifmedia_description ifm_subtype_shared_aliases[] =
794 IFM_SUBTYPE_SHARED_ALIASES;
795
796 struct ifmedia_description ifm_shared_option_descriptions[] =
797 IFM_SHARED_OPTION_DESCRIPTIONS;
798
799 struct ifmedia_type_to_subtype {
800 struct {
801 struct ifmedia_description *desc;
802 int alias;
803 } subtypes[5];
804 struct {
805 struct ifmedia_description *desc;
806 int alias;
807 } options[3];
808 };
809
810 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
811 struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
812 {
813 {
814 { &ifm_subtype_shared_descriptions[0], 0 },
815 { &ifm_subtype_shared_aliases[0], 1 },
816 { &ifm_subtype_ethernet_descriptions[0], 0 },
817 { &ifm_subtype_ethernet_aliases[0], 1 },
818 { NULL, 0 },
819 },
820 {
821 { &ifm_shared_option_descriptions[0], 0 },
822 { &ifm_subtype_ethernet_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_tokenring_descriptions[0], 0 },
831 { &ifm_subtype_tokenring_aliases[0], 1 },
832 { NULL, 0 },
833 },
834 {
835 { &ifm_shared_option_descriptions[0], 0 },
836 { &ifm_subtype_tokenring_option_descriptions[0], 1 },
837 { NULL, 0 },
838 },
839 },
840 {
841 {
842 { &ifm_subtype_shared_descriptions[0], 0 },
843 { &ifm_subtype_shared_aliases[0], 1 },
844 { &ifm_subtype_fddi_descriptions[0], 0 },
845 { &ifm_subtype_fddi_aliases[0], 1 },
846 { NULL, 0 },
847 },
848 {
849 { &ifm_shared_option_descriptions[0], 0 },
850 { &ifm_subtype_fddi_option_descriptions[0], 1 },
851 { NULL, 0 },
852 },
853 },
854 };
855
856 int
857 get_media_subtype(type, val)
858 int type;
859 char *val;
860 {
861 struct ifmedia_description *desc;
862 struct ifmedia_type_to_subtype *ttos;
863 int rval, i;
864
865 /* Find the top-level interface type. */
866 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
867 desc->ifmt_string != NULL; desc++, ttos++)
868 if (type == desc->ifmt_word)
869 break;
870 if (desc->ifmt_string == NULL)
871 errx(1, "unknown media type 0x%x", type);
872
873 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
874 rval = lookup_media_word(ttos->subtypes[i].desc, val);
875 if (rval != -1)
876 return (rval);
877 }
878 errx(1, "unknown media subtype: %s", val);
879 /* NOTREACHED */
880 }
881
882 int
883 get_media_options(type, val)
884 int type;
885 char *val;
886 {
887 struct ifmedia_description *desc;
888 struct ifmedia_type_to_subtype *ttos;
889 char *optlist;
890 int option = 0, i, rval = 0;
891
892 /* We muck with the string, so copy it. */
893 optlist = strdup(val);
894 if (optlist == NULL)
895 err(1, "strdup");
896 val = optlist;
897
898 /* Find the top-level interface type. */
899 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
900 desc->ifmt_string != NULL; desc++, ttos++)
901 if (type == desc->ifmt_word)
902 break;
903 if (desc->ifmt_string == NULL)
904 errx(1, "unknown media type 0x%x", type);
905
906 /*
907 * Look up the options in the user-provided comma-separated
908 * list.
909 */
910 for (; (val = strtok(val, ",")) != NULL; val = NULL) {
911 for (i = 0; ttos->options[i].desc != NULL; i++) {
912 option = lookup_media_word(ttos->options[i].desc, val);
913 if (option != -1)
914 break;
915 }
916 if (option == 0)
917 errx(1, "unknown option: %s", val);
918 rval |= option;
919 }
920
921 free(optlist);
922 return (rval);
923 }
924
925 int
926 lookup_media_word(desc, val)
927 struct ifmedia_description *desc;
928 char *val;
929 {
930
931 for (; desc->ifmt_string != NULL; desc++)
932 if (strcasecmp(desc->ifmt_string, val) == 0)
933 return (desc->ifmt_word);
934
935 return (-1);
936 }
937
938 void
939 print_media_word(ifmw)
940 int ifmw;
941 {
942 struct ifmedia_description *desc;
943 struct ifmedia_type_to_subtype *ttos;
944 int seen_option = 0, i;
945
946 /* Find the top-level interface type. */
947 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
948 desc->ifmt_string != NULL; desc++, ttos++)
949 if (IFM_TYPE(ifmw) == desc->ifmt_word)
950 break;
951 if (desc->ifmt_string == NULL) {
952 printf("<unknown type>");
953 return;
954 }
955
956 /*
957 * Don't print the top-level type; it's not like we can
958 * change it, or anything.
959 */
960
961 /* Find subtype. */
962 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
963 if (ttos->subtypes[i].alias)
964 continue;
965 for (desc = ttos->subtypes[i].desc;
966 desc->ifmt_string != NULL; desc++) {
967 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
968 goto got_subtype;
969 }
970 }
971
972 /* Falling to here means unknown subtype. */
973 printf("<unknown subtype>");
974 return;
975
976 got_subtype:
977 printf("%s", desc->ifmt_string);
978
979 /* Find options. */
980 for (i = 0; ttos->options[i].desc != NULL; i++) {
981 if (ttos->options[i].alias)
982 continue;
983 for (desc = ttos->options[i].desc;
984 desc->ifmt_string != NULL; desc++) {
985 if (ifmw & desc->ifmt_word) {
986 if (seen_option == 0)
987 printf(" <");
988 printf("%s%s", seen_option++ ? "," : "",
989 desc->ifmt_string);
990 }
991 }
992 }
993 printf("%s", seen_option ? ">" : "");
994 }
995
996 /**********************************************************************
997 * ...until here.
998 **********************************************************************/
999
1000 #define IFFBITS \
1001 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
1002 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
1003
1004 /*
1005 * Print the status of the interface. If an address family was
1006 * specified, show it and it only; otherwise, show them all.
1007 */
1008 void
1009 status(ap, alen)
1010 const u_int8_t *ap;
1011 int alen;
1012 {
1013 register struct afswtch *p = afp;
1014 struct ifmediareq ifmr;
1015 int *media_list, i;
1016
1017 printf("%s: ", name);
1018 printb("flags", flags, IFFBITS);
1019 if (metric)
1020 printf(" metric %d", metric);
1021 if (mtu)
1022 printf(" mtu %d", mtu);
1023 putchar('\n');
1024 if (ap && alen > 0) {
1025 printf("\taddress:");
1026 for (i = 0; i < alen; i++, ap++)
1027 printf("%c%02x", i > 0 ? ':' : ' ', *ap);
1028 putchar('\n');
1029 }
1030
1031 (void) memset(&ifmr, 0, sizeof(ifmr));
1032 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
1033
1034 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
1035 /*
1036 * Interface doesn't support SIOC{G,S}IFMEDIA.
1037 */
1038 goto proto_status;
1039 }
1040
1041 if (ifmr.ifm_count == 0) {
1042 warnx("%s: no media types?", name);
1043 goto proto_status;
1044 }
1045
1046 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
1047 if (media_list == NULL)
1048 err(1, "malloc");
1049 ifmr.ifm_ulist = media_list;
1050
1051 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
1052 err(1, "SIOCGIFMEDIA");
1053
1054 printf("\tmedia: ");
1055 print_media_word(ifmr.ifm_current);
1056 if (ifmr.ifm_active != ifmr.ifm_current) {
1057 putchar(' ');
1058 putchar('(');
1059 print_media_word(ifmr.ifm_active);
1060 putchar(')');
1061 }
1062
1063 if (ifmr.ifm_status & IFM_AVALID) {
1064 printf(" status: ");
1065 switch (IFM_TYPE(ifmr.ifm_active)) {
1066 case IFM_ETHER:
1067 if (ifmr.ifm_status & IFM_ACTIVE)
1068 printf("active");
1069 else
1070 printf("no carrier");
1071 break;
1072
1073 case IFM_FDDI:
1074 case IFM_TOKEN:
1075 if (ifmr.ifm_status & IFM_ACTIVE)
1076 printf("inserted");
1077 else
1078 printf("no ring");
1079 break;
1080 }
1081 }
1082
1083 putchar('\n');
1084
1085 if (mflag) {
1086 printf("\tsupported media:");
1087 for (i = 0; i < ifmr.ifm_count; i++) {
1088 putchar(' ');
1089 print_media_word(media_list[i]);
1090 }
1091 putchar('\n');
1092 }
1093
1094 free(media_list);
1095
1096 proto_status:
1097 if ((p = afp) != NULL) {
1098 (*p->af_status)(1);
1099 } else for (p = afs; p->af_name; p++) {
1100 ifr.ifr_addr.sa_family = p->af_af;
1101 (*p->af_status)(0);
1102 }
1103 }
1104
1105 void
1106 in_status(force)
1107 int force;
1108 {
1109 struct sockaddr_in *sin;
1110
1111 getsock(AF_INET);
1112 if (s < 0) {
1113 if (errno == EPROTONOSUPPORT)
1114 return;
1115 err(1, "socket");
1116 }
1117 (void) memset(&ifr, 0, sizeof(ifr));
1118 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1119 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1120 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1121 if (!force)
1122 return;
1123 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1124 } else
1125 warn("SIOCGIFADDR");
1126 }
1127 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1128 sin = (struct sockaddr_in *)&ifr.ifr_addr;
1129 printf("\tinet %s ", inet_ntoa(sin->sin_addr));
1130 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1131 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
1132 if (errno != EADDRNOTAVAIL)
1133 warn("SIOCGIFNETMASK");
1134 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1135 } else
1136 netmask.sin_addr =
1137 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
1138 if (flags & IFF_POINTOPOINT) {
1139 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1140 if (errno == EADDRNOTAVAIL)
1141 (void) memset(&ifr.ifr_addr, 0,
1142 sizeof(ifr.ifr_addr));
1143 else
1144 warn("SIOCGIFDSTADDR");
1145 }
1146 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1147 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
1148 printf("--> %s ", inet_ntoa(sin->sin_addr));
1149 }
1150 printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
1151 if (flags & IFF_BROADCAST) {
1152 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
1153 if (errno == EADDRNOTAVAIL)
1154 (void) memset(&ifr.ifr_addr, 0,
1155 sizeof(ifr.ifr_addr));
1156 else
1157 warn("SIOCGIFBRDADDR");
1158 }
1159 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1160 sin = (struct sockaddr_in *)&ifr.ifr_addr;
1161 if (sin->sin_addr.s_addr != 0)
1162 printf("broadcast %s", inet_ntoa(sin->sin_addr));
1163 }
1164 putchar('\n');
1165 }
1166
1167 #ifndef INET_ONLY
1168
1169 void
1170 at_status(force)
1171 int force;
1172 {
1173 struct sockaddr_at *sat, null_sat;
1174 struct netrange *nr;
1175
1176 getsock(AF_APPLETALK);
1177 if (s < 0) {
1178 if (errno == EPROTONOSUPPORT)
1179 return;
1180 err(1, "socket");
1181 }
1182 (void) memset(&ifr, 0, sizeof(ifr));
1183 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1184 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1185 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1186 if (!force)
1187 return;
1188 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1189 } else
1190 warn("SIOCGIFADDR");
1191 }
1192 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1193 sat = (struct sockaddr_at *)&ifr.ifr_addr;
1194
1195 (void) memset(&null_sat, 0, sizeof(null_sat));
1196
1197 nr = (struct netrange *) &sat->sat_zero;
1198 printf("\tatalk %d.%d range %d-%d phase %d",
1199 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1200 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
1201 if (flags & IFF_POINTOPOINT) {
1202 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1203 if (errno == EADDRNOTAVAIL)
1204 (void) memset(&ifr.ifr_addr, 0,
1205 sizeof(ifr.ifr_addr));
1206 else
1207 warn("SIOCGIFDSTADDR");
1208 }
1209 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1210 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr;
1211 if (!sat)
1212 sat = &null_sat;
1213 printf("--> %d.%d",
1214 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
1215 }
1216 if (flags & IFF_BROADCAST) {
1217 /* note RTAX_BRD overlap with IFF_POINTOPOINT */
1218 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr;
1219 if (sat)
1220 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net),
1221 sat->sat_addr.s_node);
1222 }
1223 putchar('\n');
1224 }
1225
1226 void
1227 xns_status(force)
1228 int force;
1229 {
1230 struct sockaddr_ns *sns;
1231
1232 getsock(AF_NS);
1233 if (s < 0) {
1234 if (errno == EPROTONOSUPPORT)
1235 return;
1236 err(1, "socket");
1237 }
1238 (void) memset(&ifr, 0, sizeof(ifr));
1239 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1240 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1241 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1242 if (!force)
1243 return;
1244 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1245 } else
1246 warn("SIOCGIFADDR");
1247 }
1248 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1249 sns = (struct sockaddr_ns *)&ifr.ifr_addr;
1250 printf("\tns %s ", ns_ntoa(sns->sns_addr));
1251 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
1252 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1253 if (errno == EADDRNOTAVAIL)
1254 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1255 else
1256 warn("SIOCGIFDSTADDR");
1257 }
1258 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1259 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
1260 printf("--> %s ", ns_ntoa(sns->sns_addr));
1261 }
1262 putchar('\n');
1263 }
1264
1265 void
1266 iso_status(force)
1267 int force;
1268 {
1269 struct sockaddr_iso *siso;
1270
1271 getsock(AF_ISO);
1272 if (s < 0) {
1273 if (errno == EPROTONOSUPPORT)
1274 return;
1275 err(1, "socket");
1276 }
1277 (void) memset(&ifr, 0, sizeof(ifr));
1278 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1279 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1280 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1281 if (!force)
1282 return;
1283 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1284 } else
1285 warn("SIOCGIFADDR");
1286 }
1287 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1288 siso = (struct sockaddr_iso *)&ifr.ifr_addr;
1289 printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
1290 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
1291 if (errno == EADDRNOTAVAIL)
1292 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1293 else
1294 warn("SIOCGIFNETMASK");
1295 } else {
1296 printf(" netmask %s ", iso_ntoa(&siso->siso_addr));
1297 }
1298 if (flags & IFF_POINTOPOINT) {
1299 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1300 if (errno == EADDRNOTAVAIL)
1301 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1302 else
1303 warn("SIOCGIFDSTADDR");
1304 }
1305 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1306 siso = (struct sockaddr_iso *)&ifr.ifr_addr;
1307 printf("--> %s ", iso_ntoa(&siso->siso_addr));
1308 }
1309 putchar('\n');
1310 }
1311
1312 #endif /* INET_ONLY */
1313
1314 #define SIN(x) ((struct sockaddr_in *) &(x))
1315 struct sockaddr_in *sintab[] = {
1316 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
1317 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
1318
1319 void
1320 in_getaddr(s, which)
1321 char *s;
1322 int which;
1323 {
1324 register struct sockaddr_in *sin = sintab[which];
1325 struct hostent *hp;
1326 struct netent *np;
1327
1328 sin->sin_len = sizeof(*sin);
1329 if (which != MASK)
1330 sin->sin_family = AF_INET;
1331
1332 if (inet_aton(s, &sin->sin_addr) == 0) {
1333 if ((hp = gethostbyname(s)) != NULL)
1334 (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
1335 else if ((np = getnetbyname(s)) != NULL)
1336 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
1337 else
1338 errx(1, "%s: bad value", s);
1339 }
1340 }
1341
1342 /*
1343 * Print a value a la the %b format of the kernel's printf
1344 */
1345 void
1346 printb(s, v, bits)
1347 char *s;
1348 register char *bits;
1349 register unsigned short v;
1350 {
1351 register int i, any = 0;
1352 register char c;
1353
1354 if (bits && *bits == 8)
1355 printf("%s=%o", s, v);
1356 else
1357 printf("%s=%x", s, v);
1358 bits++;
1359 if (bits) {
1360 putchar('<');
1361 while ((i = *bits++) != 0) {
1362 if (v & (1 << (i-1))) {
1363 if (any)
1364 putchar(',');
1365 any = 1;
1366 for (; (c = *bits) > 32; bits++)
1367 putchar(c);
1368 } else
1369 for (; *bits > 32; bits++)
1370 ;
1371 }
1372 putchar('>');
1373 }
1374 }
1375
1376 #ifndef INET_ONLY
1377
1378 void
1379 at_getaddr(addr, which)
1380 char *addr;
1381 int which;
1382 {
1383 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr;
1384 u_int net, node;
1385
1386 sat->sat_family = AF_APPLETALK;
1387 sat->sat_len = sizeof(*sat);
1388 if (which == MASK)
1389 errx(1, "AppleTalk does not use netmasks\n");
1390 if (sscanf(addr, "%u.%u", &net, &node) != 2
1391 || net == 0 || net > 0xffff || node == 0 || node > 0xfe)
1392 errx(1, "%s: illegal address", addr);
1393 sat->sat_addr.s_net = htons(net);
1394 sat->sat_addr.s_node = node;
1395 }
1396
1397 void
1398 setatrange(range, d)
1399 char *range;
1400 int d;
1401 {
1402 u_short first = 123, last = 123;
1403
1404 if (sscanf(range, "%hu-%hu", &first, &last) != 2
1405 || first == 0 || first > 0xffff
1406 || last == 0 || last > 0xffff || first > last)
1407 errx(1, "%s: illegal net range: %u-%u", range, first, last);
1408 at_nr.nr_firstnet = htons(first);
1409 at_nr.nr_lastnet = htons(last);
1410 }
1411
1412 void
1413 setatphase(phase, d)
1414 char *phase;
1415 int d;
1416 {
1417 if (!strcmp(phase, "1"))
1418 at_nr.nr_phase = 1;
1419 else if (!strcmp(phase, "2"))
1420 at_nr.nr_phase = 2;
1421 else
1422 errx(1, "%s: illegal phase", phase);
1423 }
1424
1425 void
1426 checkatrange(sat)
1427 struct sockaddr_at *sat;
1428 {
1429 if (at_nr.nr_phase == 0)
1430 at_nr.nr_phase = 2; /* Default phase 2 */
1431 if (at_nr.nr_firstnet == 0)
1432 at_nr.nr_firstnet = /* Default range of one */
1433 at_nr.nr_lastnet = sat->sat_addr.s_net;
1434 printf("\tatalk %d.%d range %d-%d phase %d\n",
1435 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1436 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase);
1437 if ((u_short) ntohs(at_nr.nr_firstnet) >
1438 (u_short) ntohs(sat->sat_addr.s_net)
1439 || (u_short) ntohs(at_nr.nr_lastnet) <
1440 (u_short) ntohs(sat->sat_addr.s_net))
1441 errx(1, "AppleTalk address is not in range");
1442 *((struct netrange *) &sat->sat_zero) = at_nr;
1443 }
1444
1445 #define SNS(x) ((struct sockaddr_ns *) &(x))
1446 struct sockaddr_ns *snstab[] = {
1447 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
1448 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
1449
1450 void
1451 xns_getaddr(addr, which)
1452 char *addr;
1453 int which;
1454 {
1455 struct sockaddr_ns *sns = snstab[which];
1456
1457 sns->sns_family = AF_NS;
1458 sns->sns_len = sizeof(*sns);
1459 sns->sns_addr = ns_addr(addr);
1460 if (which == MASK)
1461 puts("Attempt to set XNS netmask will be ineffectual");
1462 }
1463
1464 #define SISO(x) ((struct sockaddr_iso *) &(x))
1465 struct sockaddr_iso *sisotab[] = {
1466 SISO(ridreq.ifr_addr), SISO(iso_addreq.ifra_addr),
1467 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
1468
1469 void
1470 iso_getaddr(addr, which)
1471 char *addr;
1472 int which;
1473 {
1474 register struct sockaddr_iso *siso = sisotab[which];
1475 siso->siso_addr = *iso_addr(addr);
1476
1477 if (which == MASK) {
1478 siso->siso_len = TSEL(siso) - (caddr_t)(siso);
1479 siso->siso_nlen = 0;
1480 } else {
1481 siso->siso_len = sizeof(*siso);
1482 siso->siso_family = AF_ISO;
1483 }
1484 }
1485
1486 void
1487 setsnpaoffset(val, d)
1488 char *val;
1489 int d;
1490 {
1491 iso_addreq.ifra_snpaoffset = atoi(val);
1492 }
1493
1494 void
1495 setnsellength(val, d)
1496 char *val;
1497 int d;
1498 {
1499 nsellength = atoi(val);
1500 if (nsellength < 0)
1501 errx(1, "Negative NSEL length is absurd");
1502 if (afp == 0 || afp->af_af != AF_ISO)
1503 errx(1, "Setting NSEL length valid only for iso");
1504 }
1505
1506 void
1507 fixnsel(s)
1508 register struct sockaddr_iso *s;
1509 {
1510 if (s->siso_family == 0)
1511 return;
1512 s->siso_tlen = nsellength;
1513 }
1514
1515 void
1516 adjust_nsellength()
1517 {
1518 fixnsel(sisotab[RIDADDR]);
1519 fixnsel(sisotab[ADDR]);
1520 fixnsel(sisotab[DSTADDR]);
1521 }
1522
1523 #endif /* INET_ONLY */
1524
1525 void
1526 usage()
1527 {
1528 fprintf(stderr,
1529 "usage: ifconfig [ -m ] interface\n%s%s%s%s%s%s%s%s%s%s%s",
1530 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ] ",
1531 "[ netmask mask ] ]\n",
1532 "\t[ metric n ]\n",
1533 "\t[ mtu n ]\n",
1534 "\t[ arp | -arp ]\n",
1535 "\t[ media mtype ]\n",
1536 "\t[ mediaopt mopts ]\n",
1537 "\t[ -mediaopt mopts ]\n",
1538 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n",
1539 " ifconfig -a [ -m ] [ -d ] [ -u ] [ af ]\n",
1540 " ifconfig -l [ -d ] [ -u ]\n");
1541 exit(1);
1542 }
1543