revert between 56095 -> 55830 in arch
[AROS.git] / workbench / network / common / C / ifconfig.c
blob88a0c9b506e69118f339ab858f977546430a903f
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 Neil Cafferkey
6 * Copyright (c) 2005 Pavel Fedin
7 * Copyright (c) 2006-2019 The AROS Dev Team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21 * MA 02111-1307, USA.
26 * Copyright (c) 1983, 1993
27 * The Regents of the University of California. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
58 #define INET_ONLY
60 #include <dos/dos.h>
62 #include <proto/exec.h>
64 #include <sys/cdefs.h>
65 #include <sys/param.h>
66 #include <sys/socket.h>
67 #include <sys/sockio.h>
69 #include <net/if.h>
70 #include <net/if_dl.h>
71 #ifdef ENABLE_MEDIA_IOCTL
72 #include <net/if_media.h>
73 #endif
74 #include <netinet/in.h>
75 #include <arpa/inet.h>
76 #ifdef ENABLE_APPLETALK
77 #include <netatalk/at.h>
78 #endif
79 #ifdef NS
80 #define NSIP
81 #include <netns/ns.h>
82 #include <netns/ns_if.h>
83 #endif
84 #include <netdb.h>
86 #define EON
87 #ifdef ISO
88 #include <netiso/iso.h>
89 #include <netiso/iso_var.h>
90 #endif
91 #if !defined(__AROS__)
92 #include <sys/protosw.h>
93 #endif
95 #include <ctype.h>
96 #if !defined(__AROS__)
97 #include <err.h>
98 #else
99 #define err(a,b)
100 #define errx(a,b,c)
101 #define warn(a)
102 #define inet_makeaddr(a,b) Inet_MakeAddr(a,b)
103 #endif
104 #include <errno.h>
105 #include <stdio.h>
106 #include <stdlib.h>
107 #include <string.h>
108 #include <unistd.h>
109 #include <proto/miami.h>
110 #include <proto/socket.h>
112 #if defined(__AROS__)
113 struct Library *SocketBase;
114 struct Library *MiamiBase;
115 #endif
117 #define SOCKET_VERSION 3
118 const TEXT version[] = "$VER: ifconfig 5.0 (04.12.2005)";
119 const TEXT socket_name[] = "bsdsocket.library";
121 struct ifreq ifr, ridreq;
122 struct ifaliasreq addreq __attribute__((aligned(4)));
123 #ifdef ISO
124 struct iso_aliasreq iso_addreq;
125 #endif
126 struct sockaddr_in netmask;
127 #ifdef ENABLE_APPLETALK
128 struct netrange at_nr; /* AppleTalk net range */
129 #endif
130 char name[30];
131 int flags, metric, mtu, setaddr, setipdst, doalias;
132 int clearaddr, s;
133 int newaddr = -1;
134 int nsellength = 1;
135 int af;
136 int dflag, mflag, lflag, uflag;
137 int reset_if_flags;
139 void notealias __P((char *, int));
140 void notrailers __P((char *, int));
141 void setifaddr __P((char *, int));
142 void setifdstaddr __P((char *, int));
143 void setifflags __P((char *, int));
144 void setifbroadaddr __P((char *, int));
145 void setifipdst __P((char *, int));
146 void setifmetric __P((char *, int));
147 void setifmtu __P((char *, int));
148 void setifnetmask __P((char *, int));
149 void setnsellength __P((char *, int));
150 void setsnpaoffset __P((char *, int));
151 void setatrange __P((char *, int));
152 void setatphase __P((char *, int));
153 #ifdef ENABLE_APPLETALK
154 void checkatrange __P ((struct sockaddr_at *));
155 #endif
156 void setmedia __P((char *, int));
157 void setmediaopt __P((char *, int));
158 void unsetmediaopt __P((char *, int));
159 #ifdef ISO
160 void fixnsel __P((struct sockaddr_iso *));
161 #endif
162 int main __P((int, char *[]));
164 #define NEXTARG 0xffffff
166 struct cmd {
167 char *c_name;
168 int c_parameter; /* NEXTARG means next argv */
169 void (*c_func) __P((char *, int));
170 } cmds[] = {
171 { "up", IFF_UP, setifflags } ,
172 { "down", -IFF_UP, setifflags },
173 { "trailers", -1, notrailers },
174 { "-trailers", 1, notrailers },
175 { "arp", -IFF_NOARP, setifflags },
176 { "-arp", IFF_NOARP, setifflags },
177 { "debug", IFF_DEBUG, setifflags },
178 { "-debug", -IFF_DEBUG, setifflags },
179 { "alias", IFF_UP, notealias },
180 { "-alias", -IFF_UP, notealias },
181 { "delete", -IFF_UP, notealias },
182 #ifdef notdef
183 #define EN_SWABIPS 0x1000
184 { "swabips", EN_SWABIPS, setifflags },
185 { "-swabips", -EN_SWABIPS, setifflags },
186 #endif
187 { "netmask", NEXTARG, setifnetmask },
188 { "metric", NEXTARG, setifmetric },
189 { "mtu", NEXTARG, setifmtu },
190 { "broadcast", NEXTARG, setifbroadaddr },
191 { "ipdst", NEXTARG, setifipdst },
192 #ifndef INET_ONLY
193 { "range", NEXTARG, setatrange },
194 { "phase", NEXTARG, setatphase },
195 { "snpaoffset", NEXTARG, setsnpaoffset },
196 { "nsellength", NEXTARG, setnsellength },
197 #endif /* INET_ONLY */
198 { "link0", IFF_LINK0, setifflags } ,
199 { "-link0", -IFF_LINK0, setifflags } ,
200 { "link1", IFF_LINK1, setifflags } ,
201 { "-link1", -IFF_LINK1, setifflags } ,
202 { "link2", IFF_LINK2, setifflags } ,
203 { "-link2", -IFF_LINK2, setifflags } ,
204 #ifdef ENABLE_MEDIA_IOCTL
205 { "media", NEXTARG, setmedia },
206 { "mediaopt", NEXTARG, setmediaopt },
207 { "-mediaopt", NEXTARG, unsetmediaopt },
208 #endif
209 { 0, 0, setifaddr },
210 { 0, 0, setifdstaddr },
213 void adjust_nsellength __P((void));
214 int getinfo __P((struct ifreq *));
215 void getsock __P((int));
216 void printall __P((void));
217 void printb __P((char *, unsigned short, char *));
218 void status __P((const u_int8_t *, int));
219 void usage __P((void));
220 #ifdef ENABLE_MEDIA_IOCTL
221 void domediaopt __P((char *, int));
222 int get_media_subtype __P((int, char *));
223 int get_media_options __P((int, char *));
224 int lookup_media_word __P((struct ifmedia_description *, char *));
225 void print_media_word __P((int));
226 #endif
228 * XNS support liberally adapted from code written at the University of
229 * Maryland principally by James O'Toole and Chris Torek.
231 void in_status __P((int));
232 void in_getaddr __P((char *, int));
233 void at_status __P((int));
234 void at_getaddr __P((char *, int));
235 void xns_status __P((int));
236 void xns_getaddr __P((char *, int));
237 void iso_status __P((int));
238 void iso_getaddr __P((char *, int));
240 /* Known address families */
241 struct afswtch {
242 char *af_name;
243 short af_af;
244 void (*af_status) __P((int));
245 void (*af_getaddr) __P((char *, int));
246 u_long af_difaddr;
247 u_long af_aifaddr;
248 caddr_t af_ridreq;
249 caddr_t af_addreq;
250 } afs[] = {
251 #define C(x) ((caddr_t) &x)
252 { "inet", AF_INET, in_status, in_getaddr,
253 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
254 #ifndef INET_ONLY /* small version, for boot media */
255 { "atalk", AF_APPLETALK, at_status, at_getaddr,
256 SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) },
257 { "ns", AF_NS, xns_status, xns_getaddr,
258 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
259 { "iso", AF_ISO, iso_status, iso_getaddr,
260 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(iso_addreq) },
261 #endif /* INET_ONLY */
262 { 0, 0, 0, 0 }
265 struct afswtch *afp; /*the address family being set or asked about*/
267 struct afswtch *lookup_af __P((const char *));
269 static void __close_bsdsocket()
271 if (MiamiBase != NULL)
273 CloseLibrary(MiamiBase);
274 MiamiBase = NULL;
276 if (SocketBase != NULL)
278 CloseLibrary(SocketBase);
279 SocketBase = NULL;
284 main(argc, argv)
285 int argc;
286 char *argv[];
288 int ch, aflag;
290 #if defined(__AROS__)
291 if (!(SocketBase = OpenLibrary(socket_name, SOCKET_VERSION)))
293 return RETURN_FAIL;
295 if (!(MiamiBase = OpenLibrary("miami.library", 0)))
297 return RETURN_FAIL;
299 atexit(__close_bsdsocket);
300 #endif
302 /* Parse command-line options */
303 aflag = mflag = 0;
304 while ((ch = getopt(argc, argv, "adlmu")) != -1) {
305 switch (ch) {
306 case 'a':
307 aflag = 1;
308 break;
310 case 'd':
311 dflag = 1;
312 break;
314 case 'l':
315 lflag = 1;
316 break;
318 case 'm':
319 mflag = 1;
320 break;
322 case 'u':
323 uflag = 1;
324 break;
326 default:
327 usage();
328 /* NOTREACHED */
331 argc -= optind;
332 argv += optind;
335 * -l means "list all interfaces", and is mutally exclusive with
336 * all other flags/commands.
338 * -a means "print status of all interfaces".
340 if (lflag && (aflag || mflag || argc))
341 usage();
342 if (aflag || lflag) {
343 if (argc > 1)
344 usage();
345 else if (argc == 1) {
346 afp = lookup_af(argv[0]);
347 if (afp == NULL)
348 usage();
350 if (afp)
351 af = ifr.ifr_addr.sa_family = afp->af_af;
352 else
353 af = ifr.ifr_addr.sa_family = afs[0].af_af;
354 printall();
355 exit(0);
358 /* Make sure there's an interface name. */
359 if (argc < 1)
360 usage();
361 (void) strncpy(name, argv[0], sizeof(name) - 1);
362 argc--; argv++;
364 /* Check for address family. */
365 afp = NULL;
366 if (argc > 0) {
367 afp = lookup_af(argv[0]);
368 if (afp != NULL) {
369 argv++;
370 argc--;
374 if (afp == NULL)
375 afp = afs;
376 af = ifr.ifr_addr.sa_family = afp->af_af;
378 /* Get information about the interface. */
379 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
380 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
381 if (getinfo(&ifr) < 0)
382 exit(1);
384 /* No more arguments means interface status. */
385 if (argc == 0) {
386 status(NULL, 0);
387 exit(0);
390 /* Process commands. */
391 while (argc > 0) {
392 struct cmd *p;
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);
409 argc--, argv++;
412 #ifndef INET_ONLY
414 if (af == AF_ISO)
415 adjust_nsellength();
417 if (af == AF_APPLETALK)
418 checkatrange((struct sockaddr_at *) &addreq.ifra_addr);
420 if (setipdst && af==AF_NS) {
421 struct nsip_req rq;
422 int size = sizeof(rq);
424 rq.rq_ns = addreq.ifra_addr;
425 rq.rq_ip = addreq.ifra_dstaddr;
427 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
428 warn("encapsulation routing");
431 #endif /* INET_ONLY */
433 if (clearaddr) {
434 int ret;
435 CopyMem(name, afp->af_ridreq, sizeof (ifr.ifr_name));
436 afp->af_ridreq[sizeof(ifr.ifr_name) - 1] = '\0';
437 if ((ret = IoctlSocket(s, afp->af_difaddr, afp->af_ridreq)) < 0) {
438 if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
439 /* means no previous address for interface */
440 } else
441 warn("SIOCDIFADDR");
444 if (newaddr > 0) {
445 CopyMem(name, afp->af_addreq, sizeof (ifr.ifr_name));
446 afp->af_addreq[sizeof(ifr.ifr_name) - 1] = '\0';
447 if (IoctlSocket(s, afp->af_aifaddr, afp->af_addreq) < 0)
448 warn("SIOCAIFADDR");
450 if (reset_if_flags && IoctlSocket(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
451 err(1, "SIOCSIFFLAGS");
452 exit(0);
455 struct afswtch *
456 lookup_af(cp)
457 const char *cp;
459 struct afswtch *a;
461 for (a = afs; a->af_name != NULL; a++)
462 if (strcmp(a->af_name, cp) == 0)
463 return (a);
464 return (NULL);
467 void
468 getsock(naf)
469 int naf;
471 static int oaf = -1;
473 if (oaf == naf)
474 return;
475 if (oaf != -1)
476 CloseSocket(s);
477 s = socket(naf, SOCK_DGRAM, 0);
478 if (s < 0)
479 oaf = -1;
480 else
481 oaf = naf;
485 getinfo(ifr)
486 struct ifreq *ifr;
489 getsock(af);
490 if (s < 0)
491 err(1, "socket");
492 if (IoctlSocket(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) {
493 #if !defined(__AROS__)
494 warn("SIOCGIFFLAGS %s", ifr->ifr_name);
495 #endif
496 return (-1);
498 flags = ifr->ifr_flags;
499 if (IoctlSocket(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) {
500 #if !defined(__AROS__)
501 warn("SIOCGIFMETRIC %s", ifr->ifr_name);
502 #endif
503 metric = 0;
504 } else
505 metric = ifr->ifr_metric;
506 if (IoctlSocket(s, SIOCGIFMTU, (caddr_t)ifr) < 0)
507 mtu = 0;
508 else
509 mtu = ifr->ifr_mtu;
510 return (0);
513 void
514 printall()
516 char inbuf[8192];
517 const struct sockaddr_dl *sdl = NULL;
518 struct ifconf ifc;
519 struct ifreq ifreq, *ifr;
520 int i, idx;
522 ifc.ifc_len = sizeof(inbuf);
523 ifc.ifc_buf = inbuf;
524 getsock(af);
525 if (s < 0)
526 err(1, "socket");
527 if (IoctlSocket(s, SIOCGIFCONF, (char *)&ifc) < 0)
528 err(1, "SIOCGIFCONF");
529 ifr = ifc.ifc_req;
530 ifreq.ifr_name[0] = '\0';
531 for (i = 0, idx = 0; i < ifc.ifc_len; ) {
532 ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i);
533 i += sizeof(ifr->ifr_name) +
534 (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
535 ? ifr->ifr_addr.sa_len
536 : sizeof(struct sockaddr));
537 if (ifr->ifr_addr.sa_family == AF_LINK)
538 sdl = (const struct sockaddr_dl *) &ifr->ifr_addr;
539 if (!strncmp(ifreq.ifr_name, ifr->ifr_name,
540 sizeof(ifr->ifr_name)))
541 continue;
542 (void) strncpy(name, ifr->ifr_name, sizeof(name));
543 ifreq = *ifr;
545 if (getinfo(&ifreq) < 0)
546 continue;
547 if (dflag && (flags & IFF_UP) != 0)
548 continue;
549 if (uflag && (flags & IFF_UP) == 0)
550 continue;
552 idx++;
554 * Are we just listing the interfaces?
556 if (lflag) {
557 if (idx > 1)
558 putchar(' ');
559 fputs(name, stdout);
560 continue;
563 if (sdl == NULL) {
564 status(NULL, 0);
565 } else {
566 status(LLADDR(sdl), sdl->sdl_alen);
567 sdl = NULL;
570 if (lflag)
571 putchar('\n');
574 #define RIDADDR 0
575 #define ADDR 1
576 #define MASK 2
577 #define DSTADDR 3
579 /*ARGSUSED*/
580 void
581 setifaddr(addr, param)
582 char *addr;
583 int param;
586 * Delay the IoctlSocket to set the interface addr until flags are all set.
587 * The address interpretation may depend on the flags,
588 * and the flags may change when the address is set.
590 setaddr++;
591 if (newaddr == -1)
592 newaddr = 1;
593 if (doalias == 0)
594 clearaddr = 1;
595 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
598 void
599 setifnetmask(addr, d)
600 char *addr;
601 int d;
603 (*afp->af_getaddr)(addr, MASK);
606 void
607 setifbroadaddr(addr, d)
608 char *addr;
609 int d;
611 (*afp->af_getaddr)(addr, DSTADDR);
614 void
615 setifipdst(addr, d)
616 char *addr;
617 int d;
619 in_getaddr(addr, DSTADDR);
620 setipdst++;
621 clearaddr = 0;
622 newaddr = 0;
625 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
626 /*ARGSUSED*/
627 void
628 notealias(addr, param)
629 char *addr;
630 int param;
632 if (setaddr && doalias == 0 && param < 0)
633 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq),
634 rqtosa(af_addreq)->sa_len);
635 doalias = param;
636 if (param < 0) {
637 clearaddr = 1;
638 newaddr = 0;
639 } else
640 clearaddr = 0;
643 /*ARGSUSED*/
644 void
645 notrailers(vname, value)
646 char *vname;
647 int value;
649 puts("Note: trailers are no longer sent, but always received");
652 /*ARGSUSED*/
653 void
654 setifdstaddr(addr, param)
655 char *addr;
656 int param;
658 (*afp->af_getaddr)(addr, DSTADDR);
661 void
662 setifflags(vname, value)
663 char *vname;
664 int value;
666 if (IoctlSocket(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
667 err(1, "SIOCGIFFLAGS");
668 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
669 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
670 flags = ifr.ifr_flags;
672 if (value < 0) {
673 value = -value;
674 flags &= ~value;
675 } else
676 flags |= value;
677 ifr.ifr_flags = flags;
678 /* if (IoctlSocket(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
679 err(1, "SIOCSIFFLAGS");*/
681 reset_if_flags = 1;
684 void
685 setifmetric(val, d)
686 char *val;
687 int d;
689 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
690 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
691 ifr.ifr_metric = atoi(val);
692 if (IoctlSocket(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
693 warn("SIOCSIFMETRIC");
696 void
697 setifmtu(val, d)
698 char *val;
699 int d;
701 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
702 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
703 ifr.ifr_mtu = atoi(val);
704 if (IoctlSocket(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
705 warn("SIOCSIFMTU");
707 #ifdef ENABLE_MEDIA_IOCTL
708 void
709 setmedia(val, d)
710 char *val;
711 int d;
713 struct ifmediareq ifmr;
714 int first_type, subtype;
716 (void) memset(&ifmr, 0, sizeof(ifmr));
717 CopyMem(name, ifmr.ifm_name, sizeof (ifmr.ifm_name));
718 ifr.ifr_name[sizeof(ifmr.ifm_name) - 1] = '\0';
720 ifmr.ifm_count = 1;
721 ifmr.ifm_ulist = &first_type;
722 if (IoctlSocket(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
724 * If we get E2BIG, the kernel is telling us
725 * that there are more, so we can ignore it.
727 if (errno != E2BIG)
728 err(1, "SIOCGIFMEDIA");
731 if (ifmr.ifm_count == 0)
732 errx(1, "%s: no media types?", name);
735 * We are primarily concerned with the top-level type.
736 * However, "current" may be only IFM_NONE, so we just look
737 * for the top-level type in the first "supported type"
738 * entry.
740 * (I'm assuming that all supported media types for a given
741 * interface will be the same top-level type..)
743 subtype = get_media_subtype(IFM_TYPE(first_type), val);
745 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
746 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
747 IFM_TYPE(first_type) | subtype;
749 if (IoctlSocket(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
750 err(1, "SIOCSIFMEDIA");
753 void
754 setmediaopt(val, d)
755 char *val;
756 int d;
759 domediaopt(val, 0);
762 void
763 unsetmediaopt(val, d)
764 int d;
765 char *val;
768 domediaopt(val, 1);
771 void
772 domediaopt(val, clear)
773 char *val;
774 int clear;
776 struct ifmediareq ifmr;
777 int *mwords, options;
779 (void) memset(&ifmr, 0, sizeof(ifmr));
780 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
783 * We must go through the motions of reading all
784 * supported media because we need to know both
785 * the current media type and the top-level type.
788 if (IoctlSocket(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
789 err(1, "SIOCGIFMEDIA");
791 if (ifmr.ifm_count == 0)
792 errx(1, "%s: no media types?", name);
794 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int));
795 if (mwords == NULL)
796 err(1, "malloc");
798 ifmr.ifm_ulist = mwords;
799 if (IoctlSocket(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
800 err(1, "SIOCGIFMEDIA");
802 options = get_media_options(IFM_TYPE(mwords[0]), val);
804 free(mwords);
806 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
807 ifr.ifr_media = ifmr.ifm_current;
808 if (clear)
809 ifr.ifr_media &= ~options;
810 else
811 ifr.ifr_media |= options;
813 if (IoctlSocket(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
814 err(1, "SIOCSIFMEDIA");
817 /**********************************************************************
818 * A good chunk of this is duplicated from sys/net/ifmedia.c
819 **********************************************************************/
821 struct ifmedia_description ifm_type_descriptions[] =
822 IFM_TYPE_DESCRIPTIONS;
824 struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
825 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
827 struct ifmedia_description ifm_subtype_ethernet_aliases[] =
828 IFM_SUBTYPE_ETHERNET_ALIASES;
830 struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
831 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
833 struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
834 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
836 struct ifmedia_description ifm_subtype_tokenring_aliases[] =
837 IFM_SUBTYPE_TOKENRING_ALIASES;
839 struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
840 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
842 struct ifmedia_description ifm_subtype_fddi_descriptions[] =
843 IFM_SUBTYPE_FDDI_DESCRIPTIONS;
845 struct ifmedia_description ifm_subtype_fddi_aliases[] =
846 IFM_SUBTYPE_FDDI_ALIASES;
848 struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
849 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
851 struct ifmedia_description ifm_subtype_shared_descriptions[] =
852 IFM_SUBTYPE_SHARED_DESCRIPTIONS;
854 struct ifmedia_description ifm_subtype_shared_aliases[] =
855 IFM_SUBTYPE_SHARED_ALIASES;
857 struct ifmedia_description ifm_shared_option_descriptions[] =
858 IFM_SHARED_OPTION_DESCRIPTIONS;
860 struct ifmedia_type_to_subtype {
861 struct {
862 struct ifmedia_description *desc;
863 int alias;
864 } subtypes[5];
865 struct {
866 struct ifmedia_description *desc;
867 int alias;
868 } options[3];
871 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */
872 struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
875 { &ifm_subtype_shared_descriptions[0], 0 },
876 { &ifm_subtype_shared_aliases[0], 1 },
877 { &ifm_subtype_ethernet_descriptions[0], 0 },
878 { &ifm_subtype_ethernet_aliases[0], 1 },
879 { NULL, 0 },
882 { &ifm_shared_option_descriptions[0], 0 },
883 { &ifm_subtype_ethernet_option_descriptions[0], 1 },
884 { NULL, 0 },
889 { &ifm_subtype_shared_descriptions[0], 0 },
890 { &ifm_subtype_shared_aliases[0], 1 },
891 { &ifm_subtype_tokenring_descriptions[0], 0 },
892 { &ifm_subtype_tokenring_aliases[0], 1 },
893 { NULL, 0 },
896 { &ifm_shared_option_descriptions[0], 0 },
897 { &ifm_subtype_tokenring_option_descriptions[0], 1 },
898 { NULL, 0 },
903 { &ifm_subtype_shared_descriptions[0], 0 },
904 { &ifm_subtype_shared_aliases[0], 1 },
905 { &ifm_subtype_fddi_descriptions[0], 0 },
906 { &ifm_subtype_fddi_aliases[0], 1 },
907 { NULL, 0 },
910 { &ifm_shared_option_descriptions[0], 0 },
911 { &ifm_subtype_fddi_option_descriptions[0], 1 },
912 { NULL, 0 },
918 get_media_subtype(type, val)
919 int type;
920 char *val;
922 struct ifmedia_description *desc;
923 struct ifmedia_type_to_subtype *ttos;
924 int rval, i;
926 /* Find the top-level interface type. */
927 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
928 desc->ifmt_string != NULL; desc++, ttos++)
929 if (type == desc->ifmt_word)
930 break;
931 if (desc->ifmt_string == NULL)
932 errx(1, "unknown media type 0x%x", type);
934 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
935 rval = lookup_media_word(ttos->subtypes[i].desc, val);
936 if (rval != -1)
937 return (rval);
939 errx(1, "unknown media subtype: %s", val);
940 /* NOTREACHED */
944 get_media_options(type, val)
945 int type;
946 char *val;
948 struct ifmedia_description *desc;
949 struct ifmedia_type_to_subtype *ttos;
950 char *optlist;
951 int option = 0, i, rval = 0;
953 /* We muck with the string, so copy it. */
954 optlist = strdup(val);
955 if (optlist == NULL)
956 err(1, "strdup");
957 val = optlist;
959 /* Find the top-level interface type. */
960 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
961 desc->ifmt_string != NULL; desc++, ttos++)
962 if (type == desc->ifmt_word)
963 break;
964 if (desc->ifmt_string == NULL)
965 errx(1, "unknown media type 0x%x", type);
968 * Look up the options in the user-provided comma-separated
969 * list.
971 for (; (val = strtok(val, ",")) != NULL; val = NULL) {
972 for (i = 0; ttos->options[i].desc != NULL; i++) {
973 option = lookup_media_word(ttos->options[i].desc, val);
974 if (option != -1)
975 break;
977 if (option == 0)
978 errx(1, "unknown option: %s", val);
979 rval |= option;
982 free(optlist);
983 return (rval);
987 lookup_media_word(desc, val)
988 struct ifmedia_description *desc;
989 char *val;
992 for (; desc->ifmt_string != NULL; desc++)
993 if (strcasecmp(desc->ifmt_string, val) == 0)
994 return (desc->ifmt_word);
996 return (-1);
999 void
1000 print_media_word(ifmw)
1001 int ifmw;
1003 struct ifmedia_description *desc;
1004 struct ifmedia_type_to_subtype *ttos;
1005 int seen_option = 0, i;
1007 /* Find the top-level interface type. */
1008 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
1009 desc->ifmt_string != NULL; desc++, ttos++)
1010 if (IFM_TYPE(ifmw) == desc->ifmt_word)
1011 break;
1012 if (desc->ifmt_string == NULL) {
1013 printf("<unknown type>");
1014 return;
1018 * Don't print the top-level type; it's not like we can
1019 * change it, or anything.
1022 /* Find subtype. */
1023 for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
1024 if (ttos->subtypes[i].alias)
1025 continue;
1026 for (desc = ttos->subtypes[i].desc;
1027 desc->ifmt_string != NULL; desc++) {
1028 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
1029 goto got_subtype;
1033 /* Falling to here means unknown subtype. */
1034 printf("<unknown subtype>");
1035 return;
1037 got_subtype:
1038 printf("%s", desc->ifmt_string);
1040 /* Find options. */
1041 for (i = 0; ttos->options[i].desc != NULL; i++) {
1042 if (ttos->options[i].alias)
1043 continue;
1044 for (desc = ttos->options[i].desc;
1045 desc->ifmt_string != NULL; desc++) {
1046 if (ifmw & desc->ifmt_word) {
1047 if (seen_option == 0)
1048 printf(" <");
1049 printf("%s%s", seen_option++ ? "," : "",
1050 desc->ifmt_string);
1054 printf("%s", seen_option ? ">" : "");
1056 #endif
1057 /**********************************************************************
1058 * ...until here.
1059 **********************************************************************/
1061 #define IFFBITS \
1062 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
1063 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
1066 * Print the status of the interface. If an address family was
1067 * specified, show it and it only; otherwise, show them all.
1069 void
1070 status(ap, alen)
1071 const u_int8_t *ap;
1072 int alen;
1074 struct afswtch *p = afp;
1075 #ifdef ENABLE_MEDIA_IOCTL
1076 struct ifmediareq ifmr;
1077 int *media_list;
1078 #endif
1079 int i;
1081 printf("%s: ", name);
1082 printb("flags", flags, IFFBITS);
1083 if (metric)
1084 printf(" metric %d", metric);
1085 if (mtu)
1086 printf(" mtu %d", mtu);
1087 putchar('\n');
1088 if (ap && alen > 0) {
1089 printf("\taddress:");
1090 for (i = 0; i < alen; i++, ap++)
1091 printf("%c%02x", i > 0 ? ':' : ' ', *ap);
1092 putchar('\n');
1094 #ifdef ENABLE_MEDIA_IOCTL
1095 (void) memset(&ifmr, 0, sizeof(ifmr));
1096 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
1098 if (IoctlSocket(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
1100 * Interface doesn't support SIOC{G,S}IFMEDIA.
1102 goto proto_status;
1105 if (ifmr.ifm_count == 0) {
1106 warnx("%s: no media types?", name);
1107 goto proto_status;
1110 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
1111 if (media_list == NULL)
1112 err(1, "malloc");
1113 ifmr.ifm_ulist = media_list;
1115 if (IoctlSocket(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
1116 err(1, "SIOCGIFMEDIA");
1118 printf("\tmedia: ");
1119 print_media_word(ifmr.ifm_current);
1120 if (ifmr.ifm_active != ifmr.ifm_current) {
1121 putchar(' ');
1122 putchar('(');
1123 print_media_word(ifmr.ifm_active);
1124 putchar(')');
1127 if (ifmr.ifm_status & IFM_AVALID) {
1128 printf(" status: ");
1129 switch (IFM_TYPE(ifmr.ifm_active)) {
1130 case IFM_ETHER:
1131 if (ifmr.ifm_status & IFM_ACTIVE)
1132 printf("active");
1133 else
1134 printf("no carrier");
1135 break;
1137 case IFM_FDDI:
1138 case IFM_TOKEN:
1139 if (ifmr.ifm_status & IFM_ACTIVE)
1140 printf("inserted");
1141 else
1142 printf("no ring");
1143 break;
1147 putchar('\n');
1149 if (mflag) {
1150 printf("\tsupported media:");
1151 for (i = 0; i < ifmr.ifm_count; i++) {
1152 putchar(' ');
1153 print_media_word(media_list[i]);
1155 putchar('\n');
1158 free(media_list);
1159 proto_status:
1160 #endif
1161 if ((p = afp) != NULL) {
1162 (*p->af_status)(1);
1163 } else for (p = afs; p->af_name; p++) {
1164 ifr.ifr_addr.sa_family = p->af_af;
1165 (*p->af_status)(0);
1169 void
1170 in_status(force)
1171 int force;
1173 struct sockaddr_in *sin;
1175 getsock(AF_INET);
1176 if (s < 0) {
1177 if (errno == EPROTONOSUPPORT)
1178 return;
1179 err(1, "socket");
1181 (void) memset(&ifr, 0, sizeof(ifr));
1182 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
1183 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1184 if (IoctlSocket(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1185 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1186 if (!force)
1187 return;
1188 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1189 } else
1190 warn("SIOCGIFADDR");
1192 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
1193 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1194 sin = (struct sockaddr_in *)&ifr.ifr_addr;
1195 printf("\tinet %s ", inet_ntoa(sin->sin_addr));
1196 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
1197 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1198 if (IoctlSocket(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
1199 if (errno != EADDRNOTAVAIL)
1200 warn("SIOCGIFNETMASK");
1201 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1202 } else {
1203 struct sockaddr_in *nm_sin = (struct sockaddr_in *)&ifr.ifr_addr;
1204 netmask.sin_addr = nm_sin->sin_addr;
1206 if (flags & IFF_POINTOPOINT) {
1207 if (IoctlSocket(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1208 if (errno == EADDRNOTAVAIL)
1209 (void) memset(&ifr.ifr_addr, 0,
1210 sizeof(ifr.ifr_addr));
1211 else
1212 warn("SIOCGIFDSTADDR");
1214 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
1215 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1216 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
1217 printf("--> %s ", inet_ntoa(sin->sin_addr));
1219 printf("netmask 0x%x ", (unsigned int)ntohl(netmask.sin_addr.s_addr));
1220 if (flags & IFF_BROADCAST) {
1221 if (IoctlSocket(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
1222 if (errno == EADDRNOTAVAIL)
1223 (void) memset(&ifr.ifr_addr, 0,
1224 sizeof(ifr.ifr_addr));
1225 else
1226 warn("SIOCGIFBRDADDR");
1228 CopyMem(name, ifr.ifr_name, sizeof (ifr.ifr_name));
1229 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1230 sin = (struct sockaddr_in *)&ifr.ifr_addr;
1231 if (sin->sin_addr.s_addr != 0)
1232 printf("broadcast %s", inet_ntoa(sin->sin_addr));
1234 putchar('\n');
1237 #ifndef INET_ONLY
1239 void
1240 at_status(force)
1241 int force;
1243 struct sockaddr_at *sat, null_sat;
1244 struct netrange *nr;
1246 getsock(AF_APPLETALK);
1247 if (s < 0) {
1248 if (errno == EPROTONOSUPPORT)
1249 return;
1250 err(1, "socket");
1252 (void) memset(&ifr, 0, sizeof(ifr));
1253 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1254 if (IoctlSocket(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1255 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1256 if (!force)
1257 return;
1258 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1259 } else
1260 warn("SIOCGIFADDR");
1262 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1263 sat = (struct sockaddr_at *)&ifr.ifr_addr;
1265 (void) memset(&null_sat, 0, sizeof(null_sat));
1267 nr = (struct netrange *) &sat->sat_zero;
1268 printf("\tatalk %d.%d range %d-%d phase %d",
1269 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1270 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
1271 if (flags & IFF_POINTOPOINT) {
1272 if (IoctlSocket(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1273 if (errno == EADDRNOTAVAIL)
1274 (void) memset(&ifr.ifr_addr, 0,
1275 sizeof(ifr.ifr_addr));
1276 else
1277 warn("SIOCGIFDSTADDR");
1279 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1280 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr;
1281 if (!sat)
1282 sat = &null_sat;
1283 printf("--> %d.%d",
1284 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
1286 if (flags & IFF_BROADCAST) {
1287 /* note RTAX_BRD overlap with IFF_POINTOPOINT */
1288 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr;
1289 if (sat)
1290 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net),
1291 sat->sat_addr.s_node);
1293 putchar('\n');
1296 void
1297 xns_status(force)
1298 int force;
1300 struct sockaddr_ns *sns;
1302 getsock(AF_NS);
1303 if (s < 0) {
1304 if (errno == EPROTONOSUPPORT)
1305 return;
1306 err(1, "socket");
1308 (void) memset(&ifr, 0, sizeof(ifr));
1309 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1310 if (IoctlSocket(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1311 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1312 if (!force)
1313 return;
1314 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1315 } else
1316 warn("SIOCGIFADDR");
1318 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1319 sns = (struct sockaddr_ns *)&ifr.ifr_addr;
1320 printf("\tns %s ", ns_ntoa(sns->sns_addr));
1321 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
1322 if (IoctlSocket(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1323 if (errno == EADDRNOTAVAIL)
1324 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1325 else
1326 warn("SIOCGIFDSTADDR");
1328 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1329 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
1330 printf("--> %s ", ns_ntoa(sns->sns_addr));
1332 putchar('\n');
1335 void
1336 iso_status(force)
1337 int force;
1339 struct sockaddr_iso *siso;
1341 getsock(AF_ISO);
1342 if (s < 0) {
1343 if (errno == EPROTONOSUPPORT)
1344 return;
1345 err(1, "socket");
1347 (void) memset(&ifr, 0, sizeof(ifr));
1348 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1349 if (IoctlSocket(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
1350 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
1351 if (!force)
1352 return;
1353 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1354 } else
1355 warn("SIOCGIFADDR");
1357 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
1358 siso = (struct sockaddr_iso *)&ifr.ifr_addr;
1359 printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
1360 if (IoctlSocket(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
1361 if (errno == EADDRNOTAVAIL)
1362 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1363 else
1364 warn("SIOCGIFNETMASK");
1365 } else {
1366 printf(" netmask %s ", iso_ntoa(&siso->siso_addr));
1368 if (flags & IFF_POINTOPOINT) {
1369 if (IoctlSocket(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
1370 if (errno == EADDRNOTAVAIL)
1371 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
1372 else
1373 warn("SIOCGIFDSTADDR");
1375 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
1376 siso = (struct sockaddr_iso *)&ifr.ifr_addr;
1377 printf("--> %s ", iso_ntoa(&siso->siso_addr));
1379 putchar('\n');
1382 #endif /* INET_ONLY */
1384 #define SIN(x) ((struct sockaddr_in *) &(x))
1385 struct sockaddr_in *sintab[] = {
1386 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
1387 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
1389 void
1390 in_getaddr(s, which)
1391 char *s;
1392 int which;
1394 struct sockaddr_in *sin = sintab[which];
1395 struct hostent *hp;
1396 struct netent *np;
1398 sin->sin_len = sizeof(*sin);
1399 if (which != MASK)
1400 sin->sin_family = AF_INET;
1402 if (inet_aton(s, &sin->sin_addr) == 0) {
1403 if ((hp = gethostbyname(s)) != NULL)
1404 (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
1405 else if ((np = getnetbyname(s)) != NULL)
1407 sin->sin_addr.s_addr = inet_makeaddr(np->n_net, INADDR_ANY);
1409 else
1410 errx(1, "%s: bad value", s);
1415 * Print a value a la the %b format of the kernel's printf
1417 void
1418 printb(s, v, bits)
1419 char *s;
1420 char *bits;
1421 unsigned short v;
1423 int i, any = 0;
1424 char c;
1426 if (bits && *bits == 8)
1427 printf("%s=%o", s, v);
1428 else
1429 printf("%s=%x", s, v);
1430 bits++;
1431 if (bits) {
1432 putchar('<');
1433 while ((i = *bits++) != 0) {
1434 if (v & (1 << (i-1))) {
1435 if (any)
1436 putchar(',');
1437 any = 1;
1438 for (; (c = *bits) > 32; bits++)
1439 putchar(c);
1440 } else
1441 for (; *bits > 32; bits++)
1444 putchar('>');
1448 #ifndef INET_ONLY
1450 void
1451 at_getaddr(addr, which)
1452 char *addr;
1453 int which;
1455 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr;
1456 u_int net, node;
1458 sat->sat_family = AF_APPLETALK;
1459 sat->sat_len = sizeof(*sat);
1460 if (which == MASK)
1461 errx(1, "AppleTalk does not use netmasks\n");
1462 if (sscanf(addr, "%u.%u", &net, &node) != 2
1463 || net == 0 || net > 0xffff || node == 0 || node > 0xfe)
1464 errx(1, "%s: illegal address", addr);
1465 sat->sat_addr.s_net = htons(net);
1466 sat->sat_addr.s_node = node;
1469 void
1470 setatrange(range, d)
1471 char *range;
1472 int d;
1474 u_short first = 123, last = 123;
1476 if (sscanf(range, "%hu-%hu", &first, &last) != 2
1477 || first == 0 || first > 0xffff
1478 || last == 0 || last > 0xffff || first > last)
1479 errx(1, "%s: illegal net range: %u-%u", range, first, last);
1480 at_nr.nr_firstnet = htons(first);
1481 at_nr.nr_lastnet = htons(last);
1484 void
1485 setatphase(phase, d)
1486 char *phase;
1487 int d;
1489 if (!strcmp(phase, "1"))
1490 at_nr.nr_phase = 1;
1491 else if (!strcmp(phase, "2"))
1492 at_nr.nr_phase = 2;
1493 else
1494 errx(1, "%s: illegal phase", phase);
1497 void
1498 checkatrange(sat)
1499 struct sockaddr_at *sat;
1501 if (at_nr.nr_phase == 0)
1502 at_nr.nr_phase = 2; /* Default phase 2 */
1503 if (at_nr.nr_firstnet == 0)
1504 at_nr.nr_firstnet = /* Default range of one */
1505 at_nr.nr_lastnet = sat->sat_addr.s_net;
1506 printf("\tatalk %d.%d range %d-%d phase %d\n",
1507 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1508 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase);
1509 if ((u_short) ntohs(at_nr.nr_firstnet) >
1510 (u_short) ntohs(sat->sat_addr.s_net)
1511 || (u_short) ntohs(at_nr.nr_lastnet) <
1512 (u_short) ntohs(sat->sat_addr.s_net))
1513 errx(1, "AppleTalk address is not in range");
1514 *((struct netrange *) &sat->sat_zero) = at_nr;
1517 #define SNS(x) ((struct sockaddr_ns *) &(x))
1518 struct sockaddr_ns *snstab[] = {
1519 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
1520 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
1522 void
1523 xns_getaddr(addr, which)
1524 char *addr;
1525 int which;
1527 struct sockaddr_ns *sns = snstab[which];
1529 sns->sns_family = AF_NS;
1530 sns->sns_len = sizeof(*sns);
1531 sns->sns_addr = ns_addr(addr);
1532 if (which == MASK)
1533 puts("Attempt to set XNS netmask will be ineffectual");
1536 #define SISO(x) ((struct sockaddr_iso *) &(x))
1537 struct sockaddr_iso *sisotab[] = {
1538 SISO(ridreq.ifr_addr), SISO(iso_addreq.ifra_addr),
1539 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
1541 void
1542 iso_getaddr(addr, which)
1543 char *addr;
1544 int which;
1546 struct sockaddr_iso *siso = sisotab[which];
1547 siso->siso_addr = *iso_addr(addr);
1549 if (which == MASK) {
1550 siso->siso_len = TSEL(siso) - (caddr_t)(siso);
1551 siso->siso_nlen = 0;
1552 } else {
1553 siso->siso_len = sizeof(*siso);
1554 siso->siso_family = AF_ISO;
1558 void
1559 setsnpaoffset(val, d)
1560 char *val;
1561 int d;
1563 iso_addreq.ifra_snpaoffset = atoi(val);
1566 void
1567 setnsellength(val, d)
1568 char *val;
1569 int d;
1571 nsellength = atoi(val);
1572 if (nsellength < 0)
1573 errx(1, "Negative NSEL length is absurd");
1574 if (afp == 0 || afp->af_af != AF_ISO)
1575 errx(1, "Setting NSEL length valid only for iso");
1578 void
1579 fixnsel(s)
1580 struct sockaddr_iso *s;
1582 if (s->siso_family == 0)
1583 return;
1584 s->siso_tlen = nsellength;
1587 void
1588 adjust_nsellength()
1590 fixnsel(sisotab[RIDADDR]);
1591 fixnsel(sisotab[ADDR]);
1592 fixnsel(sisotab[DSTADDR]);
1595 #endif /* INET_ONLY */
1597 void
1598 usage()
1600 fprintf(stderr,
1601 "usage: ifconfig [ -m ] interface\n%s%s%s%s%s%s%s%s%s%s%s",
1602 "\t[ af [alias | -alias | delete] [ address [ dest_addr ] ] [ up ] [ down ] ",
1603 "[ netmask mask ] ]\n",
1604 "\t[ metric n ]\n",
1605 "\t[ mtu n ]\n",
1606 "\t[ arp | -arp ]\n",
1607 #ifdef ENABLE_MEDIA_IOCTL
1608 "\t[ media mtype ]\n",
1609 "\t[ mediaopt mopts ]\n",
1610 "\t[ -mediaopt mopts ]\n",
1611 #else
1612 "","","",
1613 #endif
1614 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n",
1615 " ifconfig -a [ -m ] [ -d ] [ -u ] [ af ]\n",
1616 " ifconfig -l [ -d ] [ -u ]\n");
1617 exit(1);