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