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