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