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