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