]>
git.saurik.com Git - apple/network_cmds.git/blob - ifconfig.tproj/ifconfig.c
0165a69c750f039137a8ccd0de6579ac65c3f61a
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 static const char copyright
[] =
36 "@(#) Copyright (c) 1983, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
42 static char sccsid
[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
44 static const char rcsid
[] =
45 "$Id: ifconfig.c,v 1.1.1.2 2000/01/11 01:48:49 wsanchez Exp $";
48 #include <sys/param.h>
49 #include <sys/ioctl.h>
50 #include <sys/socket.h>
51 #include <sys/sysctl.h>
55 #include <net/if_var.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58 #include <net/route.h>
61 #include <netinet/in.h>
62 #include <netinet/in_var.h>
63 #include <arpa/inet.h>
79 struct ifreq ifr
, ridreq
;
80 struct ifaliasreq addreq
;
81 struct sockaddr_in netmask
;
96 void Perror
__P((const char *cmd
));
98 int ifconfig
__P((int argc
, char *const *argv
, const struct afswtch
*afp
));
99 void notealias
__P((const char *, int, int, const struct afswtch
*afp
));
100 void printb
__P((const char *s
, unsigned value
, const char *bits
));
101 void rt_xaddrs
__P((caddr_t
, caddr_t
, struct rt_addrinfo
*));
102 void status
__P((const struct afswtch
*afp
, int addrcount
,
103 struct sockaddr_dl
*sdl
, struct if_msghdr
*ifm
,
104 struct ifa_msghdr
*ifam
));
105 void usage
__P((void));
107 typedef void c_func
__P((const char *cmd
, int arg
, int s
, const struct afswtch
*afp
));
109 c_func setifaddr
, setifbroadaddr
, setifdstaddr
, setifnetmask
;
111 c_func setifflags
, setifmetric
, setifmtu
;
114 #define NEXTARG 0xffffff
119 int c_parameter
; /* NEXTARG means next argv */
120 void (*c_func
) __P((const char *, int, int, const struct afswtch
*afp
));
122 { "up", IFF_UP
, setifflags
} ,
123 { "down", -IFF_UP
, setifflags
},
124 { "arp", -IFF_NOARP
, setifflags
},
125 { "-arp", IFF_NOARP
, setifflags
},
126 { "debug", IFF_DEBUG
, setifflags
},
127 { "-debug", -IFF_DEBUG
, setifflags
},
128 { "alias", IFF_UP
, notealias
},
129 { "-alias", -IFF_UP
, notealias
},
130 { "delete", -IFF_UP
, notealias
},
132 #define EN_SWABIPS 0x1000
133 { "swabips", EN_SWABIPS
, setifflags
},
134 { "-swabips", -EN_SWABIPS
, setifflags
},
136 { "netmask", NEXTARG
, setifnetmask
},
137 { "range", NEXTARG
, 0 },
138 { "phase", NEXTARG
, 0 },
139 { "metric", NEXTARG
, setifmetric
},
140 { "broadcast", NEXTARG
, setifbroadaddr
},
141 { "ipdst", NEXTARG
, setifipdst
},
142 { "link0", IFF_LINK0
, setifflags
},
143 { "-link0", -IFF_LINK0
, setifflags
},
144 { "link1", IFF_LINK1
, setifflags
},
145 { "-link1", -IFF_LINK1
, setifflags
},
146 { "link2", IFF_LINK2
, setifflags
},
147 { "-link2", -IFF_LINK2
, setifflags
},
149 { "media", NEXTARG
, setmedia
},
150 { "mediaopt", NEXTARG
, setmediaopt
},
151 { "-mediaopt", NEXTARG
, unsetmediaopt
},
153 { "normal", -IFF_LINK0
, setifflags
},
154 { "compress", IFF_LINK0
, setifflags
},
155 { "noicmp", IFF_LINK1
, setifflags
},
156 { "mtu", NEXTARG
, setifmtu
},
158 { 0, 0, setifdstaddr
},
162 * XNS support liberally adapted from code written at the University of
163 * Maryland principally by James O'Toole and Chris Torek.
165 typedef void af_status
__P((int, struct rt_addrinfo
*));
166 typedef void af_getaddr
__P((const char *, int));
168 af_status in_status
, ipx_status
, at_status
, ether_status
;
169 af_getaddr in_getaddr
, ipx_getaddr
, at_getaddr
;
171 /* Known address families */
176 af_status
*af_status
;
177 af_getaddr
*af_getaddr
;
183 #define C(x) ((caddr_t) &x)
184 { "inet", AF_INET
, in_status
, in_getaddr
,
185 SIOCDIFADDR
, SIOCAIFADDR
, C(ridreq
), C(addreq
) },
186 { "ether", AF_INET
, ether_status
, NULL
}, /* XXX not real!! */
187 #if 0 /* XXX conflicts with the media command */
189 { "media", AF_INET
, media_status
, NULL
}, /* XXX not real!! */
196 * Expand the compacted form of addresses as returned via the
197 * configuration read via sysctl().
201 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
202 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
205 rt_xaddrs(cp
, cplim
, rtinfo
)
207 struct rt_addrinfo
*rtinfo
;
212 memset(rtinfo
->rti_info
, 0, sizeof(rtinfo
->rti_info
));
213 for (i
= 0; (i
< RTAX_MAX
) && (cp
< cplim
); i
++) {
214 if ((rtinfo
->rti_addrs
& (1 << i
)) == 0)
216 rtinfo
->rti_info
[i
] = sa
= (struct sockaddr
*)cp
;
225 fprintf(stderr
, "%s\n%s\n%s\n%s\n",
226 "usage: ifconfig interface address_family [address [dest_address]]",
228 " ifconfig -a [-d] [-u] [address_family]",
229 " ifconfig -l [-d] [-u] [address_family]");
239 int all
, namesonly
, downonly
, uponly
;
240 int foundit
= 0, need_nl
= 0;
241 const struct afswtch
*afp
= 0;
243 struct if_msghdr
*ifm
, *nextifm
;
244 struct ifa_msghdr
*ifam
;
245 struct sockaddr_dl
*sdl
;
246 char *buf
, *lim
, *next
;
252 /* Parse leading line options */
253 all
= downonly
= uponly
= namesonly
= 0;
254 while ((c
= getopt(argc
, argv
, "adlmu")) != -1) {
256 case 'a': /* scan all interfaces */
259 case 'l': /* scan interface names only */
262 case 'd': /* restrict scan to "down" interfaces */
265 case 'u': /* restrict scan to "up" interfaces */
268 case 'm': /* show media choices in status */
269 /* ignored for compatibility */
279 /* -l cannot be used with -a or -m */
280 if (namesonly
&& all
)
284 if (uponly
&& downonly
)
287 /* -a and -l allow an address family arg to limit the output */
288 if (all
|| namesonly
) {
293 for (afp
= afs
; afp
->af_name
; afp
++)
294 if (strcmp(afp
->af_name
, *argv
) == 0) {
298 if (afp
->af_name
== NULL
)
300 /* leave with afp non-zero */
303 /* not listing, need an argument */
307 strncpy(name
, *argv
, sizeof(name
));
311 /* Check for address family */
313 for (afp
= afs
; afp
->af_name
; afp
++)
314 if (strcmp(afp
->af_name
, *argv
) == 0) {
318 if (afp
->af_name
== NULL
)
319 afp
= NULL
; /* not a family, NULL */
325 mib
[3] = 0; /* address family */
326 mib
[4] = NET_RT_IFLIST
;
329 /* if particular family specified, only ask about it */
333 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
334 errx(1, "iflist-sysctl-estimate");
335 if ((buf
= malloc(needed
)) == NULL
)
337 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
338 errx(1, "actual retrieval of interface table");
344 ifm
= (struct if_msghdr
*)next
;
346 if (ifm
->ifm_type
== RTM_IFINFO
) {
347 sdl
= (struct sockaddr_dl
*)(ifm
+ 1);
348 flags
= ifm
->ifm_flags
;
350 fprintf(stderr
, "out of sync parsing NET_RT_IFLIST\n");
351 fprintf(stderr
, "expected %d, got %d\n", RTM_IFINFO
,
353 fprintf(stderr
, "msglen = %d\n", ifm
->ifm_msglen
);
354 fprintf(stderr
, "buf:%p, next:%p, lim:%p\n", buf
, next
,
359 next
+= ifm
->ifm_msglen
;
364 nextifm
= (struct if_msghdr
*)next
;
366 if (nextifm
->ifm_type
!= RTM_NEWADDR
)
370 ifam
= (struct ifa_msghdr
*)nextifm
;
373 next
+= nextifm
->ifm_msglen
;
376 if (all
|| namesonly
) {
378 if ((flags
& IFF_UP
) == 0)
379 continue; /* not up */
382 continue; /* not down */
383 strncpy(name
, sdl
->sdl_data
, sdl
->sdl_nlen
);
384 name
[sdl
->sdl_nlen
] = '\0';
387 afp
->af_status
!= ether_status
||
388 sdl
->sdl_type
== IFT_ETHER
) {
397 if (strlen(name
) != sdl
->sdl_nlen
)
398 continue; /* not same len */
399 if (strncmp(name
, sdl
->sdl_data
, sdl
->sdl_nlen
) != 0)
400 continue; /* not same name */
404 ifconfig(argc
, argv
, afp
);
406 status(afp
, addrcount
, sdl
, ifm
, ifam
);
408 if (all
== 0 && namesonly
== 0) {
409 foundit
++; /* flag it as 'done' */
415 if (namesonly
&& need_nl
> 0)
418 if (all
== 0 && namesonly
== 0 && foundit
== 0)
419 errx(1, "interface %s does not exist", name
);
427 ifconfig(argc
, argv
, afp
)
430 const struct afswtch
*afp
;
436 ifr
.ifr_addr
.sa_family
= afp
->af_af
;
437 strncpy(ifr
.ifr_name
, name
, sizeof ifr
.ifr_name
);
439 if ((s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0)) < 0)
443 register const struct cmd
*p
;
445 for (p
= cmds
; p
->c_name
; p
++)
446 if (strcmp(*argv
, p
->c_name
) == 0)
448 if (p
->c_name
== 0 && setaddr
)
449 p
++; /* got src, do dst */
451 if (p
->c_parameter
== NEXTARG
) {
453 errx(1, "'%s' requires argument",
455 (*p
->c_func
)(argv
[1], 0, s
, afp
);
458 (*p
->c_func
)(*argv
, p
->c_parameter
, s
, afp
);
464 if (afp
->af_ridreq
== NULL
|| afp
->af_difaddr
== 0) {
465 warnx("interface %s cannot change %s addresses!",
472 strncpy(afp
->af_ridreq
, name
, sizeof ifr
.ifr_name
);
473 if ((ret
= ioctl(s
, afp
->af_difaddr
, afp
->af_ridreq
)) < 0) {
474 if (errno
== EADDRNOTAVAIL
&& (doalias
>= 0)) {
475 /* means no previous address for interface */
477 Perror("ioctl (SIOCDIFADDR)");
481 if (afp
->af_ridreq
== NULL
|| afp
->af_difaddr
== 0) {
482 warnx("interface %s cannot change %s addresses!",
488 strncpy(afp
->af_addreq
, name
, sizeof ifr
.ifr_name
);
489 if (ioctl(s
, afp
->af_aifaddr
, afp
->af_addreq
) < 0)
490 Perror("ioctl (SIOCAIFADDR)");
502 setifaddr(addr
, param
, s
, afp
)
506 const struct afswtch
*afp
;
509 * Delay the ioctl to set the interface addr until flags are all set.
510 * The address interpretation may depend on the flags,
511 * and the flags may change when the address is set.
516 (*afp
->af_getaddr
)(addr
, (doalias
>= 0 ? ADDR
: RIDADDR
));
520 setifnetmask(addr
, dummy
, s
, afp
)
524 const struct afswtch
*afp
;
526 (*afp
->af_getaddr
)(addr
, MASK
);
530 setifbroadaddr(addr
, dummy
, s
, afp
)
534 const struct afswtch
*afp
;
536 (*afp
->af_getaddr
)(addr
, DSTADDR
);
540 setifipdst(addr
, dummy
, s
, afp
)
544 const struct afswtch
*afp
;
546 in_getaddr(addr
, DSTADDR
);
551 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
554 notealias(addr
, param
, s
, afp
)
558 const struct afswtch
*afp
;
560 if (setaddr
&& doalias
== 0 && param
< 0)
561 bcopy((caddr_t
)rqtosa(af_addreq
),
562 (caddr_t
)rqtosa(af_ridreq
),
563 rqtosa(af_addreq
)->sa_len
);
574 setifdstaddr(addr
, param
, s
, afp
)
578 const struct afswtch
*afp
;
580 (*afp
->af_getaddr
)(addr
, DSTADDR
);
584 setifflags(vname
, value
, s
, afp
)
588 const struct afswtch
*afp
;
590 if (ioctl(s
, SIOCGIFFLAGS
, (caddr_t
)&ifr
) < 0) {
591 Perror("ioctl (SIOCGIFFLAGS)");
594 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
595 flags
= ifr
.ifr_flags
;
602 ifr
.ifr_flags
= flags
;
603 if (ioctl(s
, SIOCSIFFLAGS
, (caddr_t
)&ifr
) < 0)
608 setifmetric(val
, dummy
, s
, afp
)
612 const struct afswtch
*afp
;
614 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
615 ifr
.ifr_metric
= atoi(val
);
616 if (ioctl(s
, SIOCSIFMETRIC
, (caddr_t
)&ifr
) < 0)
617 warn("ioctl (set metric)");
621 setifmtu(val
, dummy
, s
, afp
)
625 const struct afswtch
*afp
;
627 strncpy(ifr
.ifr_name
, name
, sizeof (ifr
.ifr_name
));
628 ifr
.ifr_mtu
= atoi(val
);
629 if (ioctl(s
, SIOCSIFMTU
, (caddr_t
)&ifr
) < 0)
630 warn("ioctl (set mtu)");
635 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6b6\7RUNNING" \
636 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
640 * Print the status of the interface. If an address family was
641 * specified, show it and it only; otherwise, show them all.
644 status(afp
, addrcount
, sdl
, ifm
, ifam
)
645 const struct afswtch
*afp
;
647 struct sockaddr_dl
*sdl
;
648 struct if_msghdr
*ifm
;
649 struct ifa_msghdr
*ifam
;
651 const struct afswtch
*p
= NULL
;
652 struct rt_addrinfo info
;
661 ifr
.ifr_addr
.sa_family
= afp
->af_af
;
662 strncpy(ifr
.ifr_name
, name
, sizeof ifr
.ifr_name
);
664 if ((s
= socket(ifr
.ifr_addr
.sa_family
, SOCK_DGRAM
, 0)) < 0)
668 * XXX is it we are doing a SIOCGIFMETRIC etc for one family.
669 * is it possible that the metric and mtu can be different for
670 * each family? If so, we have a format problem, because the
671 * metric and mtu is printed on the global the flags line.
673 if (ioctl(s
, SIOCGIFMETRIC
, (caddr_t
)&ifr
) < 0)
674 warn("ioctl (SIOCGIFMETRIC)");
676 metric
= ifr
.ifr_metric
;
678 if (ioctl(s
, SIOCGIFMTU
, (caddr_t
)&ifr
) < 0)
679 warn("ioctl (SIOCGIFMTU)");
683 printf("%s: ", name
);
684 printb("flags", flags
, IFFBITS
);
686 printf(" metric %d", metric
);
688 printf(" mtu %d", mtu
);
691 while (addrcount
> 0) {
693 info
.rti_addrs
= ifam
->ifam_addrs
;
695 /* Expand the compacted addresses */
696 rt_xaddrs((char *)(ifam
+ 1), ifam
->ifam_msglen
+ (char *)ifam
,
700 if (afp
->af_af
== info
.rti_info
[RTAX_IFA
]->sa_family
&&
702 afp
->af_status
!= media_status
&&
704 afp
->af_status
!= ether_status
) {
706 (*p
->af_status
)(s
, &info
);
708 } else for (p
= afs
; p
->af_name
; p
++) {
709 if (p
->af_af
== info
.rti_info
[RTAX_IFA
]->sa_family
&&
711 p
->af_status
!= media_status
&&
713 p
->af_status
!= ether_status
)
714 (*p
->af_status
)(s
, &info
);
717 ifam
= (struct ifa_msghdr
*)((char *)ifam
+ ifam
->ifam_msglen
);
719 if (allfamilies
|| afp
->af_status
== ether_status
)
720 ether_status(s
, (struct rt_addrinfo
*)sdl
);
722 if (allfamilies
|| afp
->af_status
== media_status
)
723 media_status(s
, NULL
);
725 if (!allfamilies
&& !p
&&
726 afp
->af_status
!= ether_status
)
727 warnx("%s has no %s interface address!", name
, afp
->af_name
);
736 struct rt_addrinfo
* info
;
738 struct sockaddr_in
*sin
, null_sin
;
740 memset(&null_sin
, 0, sizeof(null_sin
));
742 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_IFA
];
743 printf("\tinet %s ", inet_ntoa(sin
->sin_addr
));
745 if (flags
& IFF_POINTOPOINT
) {
746 /* note RTAX_BRD overlap with IFF_BROADCAST */
747 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_BRD
];
750 printf("--> %s ", inet_ntoa(sin
->sin_addr
));
753 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_NETMASK
];
756 printf("netmask 0x%lx ", (unsigned long)ntohl(sin
->sin_addr
.s_addr
));
758 if (flags
& IFF_BROADCAST
) {
759 /* note RTAX_BRD overlap with IFF_POINTOPOINT */
760 sin
= (struct sockaddr_in
*)info
->rti_info
[RTAX_BRD
];
761 if (sin
&& sin
->sin_addr
.s_addr
!= 0)
762 printf("broadcast %s", inet_ntoa(sin
->sin_addr
));
768 ether_status(s
, info
)
770 struct rt_addrinfo
*info
;
774 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)info
;
776 cp
= (char *)LLADDR(sdl
);
777 if ((n
= sdl
->sdl_alen
) > 0) {
778 if (sdl
->sdl_type
== IFT_ETHER
)
781 printf ("\tlladdr ");
783 printf("%02x%c",*cp
++ & 0xff, n
>0? ':' : ' ');
795 errx(1, "%s: no such interface", cmd
);
799 errx(1, "%s: permission denied", cmd
);
807 #define SIN(x) ((struct sockaddr_in *) &(x))
808 struct sockaddr_in
*sintab
[] = {
809 SIN(ridreq
.ifr_addr
), SIN(addreq
.ifra_addr
),
810 SIN(addreq
.ifra_mask
), SIN(addreq
.ifra_broadaddr
)};
817 register struct sockaddr_in
*sin
= sintab
[which
];
821 sin
->sin_len
= sizeof(*sin
);
823 sin
->sin_family
= AF_INET
;
825 if (inet_aton(s
, &sin
->sin_addr
))
827 if ((hp
= gethostbyname(s
)) != 0)
828 bcopy(hp
->h_addr
, (char *)&sin
->sin_addr
,
829 MIN(hp
->h_length
, sizeof(sin
->sin_addr
)));
830 else if ((np
= getnetbyname(s
)) != 0)
831 sin
->sin_addr
= inet_makeaddr(np
->n_net
, INADDR_ANY
);
833 errx(1, "%s: bad value", s
);
837 * Print a value a la the %b format of the kernel's printf
843 register const char *bits
;
845 register int i
, any
= 0;
848 if (bits
&& *bits
== 8)
849 printf("%s=%o", s
, v
);
851 printf("%s=%x", s
, v
);
855 while ((i
= *bits
++) != '\0') {
856 if (v
& (1 << (i
-1))) {
860 for (; (c
= *bits
) > 32; bits
++)
863 for (; *bits
> 32; bits
++)