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