ifconfig.c revision 63473
152419Sjulian/* 252419Sjulian * Copyright (c) 1983, 1993 3139823Simp * The Regents of the University of California. All rights reserved. 4139823Simp * 5139823Simp * Redistribution and use in source and binary forms, with or without 652419Sjulian * modification, are permitted provided that the following conditions 752419Sjulian * are met: 852419Sjulian * 1. Redistributions of source code must retain the above copyright 952419Sjulian * notice, this list of conditions and the following disclaimer. 1052419Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1152419Sjulian * notice, this list of conditions and the following disclaimer in the 1252419Sjulian * documentation and/or other materials provided with the distribution. 1352419Sjulian * 3. All advertising materials mentioning features or use of this software 1452419Sjulian * must display the following acknowledgement: 1552419Sjulian * This product includes software developed by the University of 1652419Sjulian * California, Berkeley and its contributors. 1752419Sjulian * 4. Neither the name of the University nor the names of its contributors 1852419Sjulian * may be used to endorse or promote products derived from this software 1952419Sjulian * without specific prior written permission. 2052419Sjulian * 2152419Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2252419Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2352419Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2452419Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2552419Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2652419Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2752419Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2852419Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2952419Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3052419Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3152419Sjulian * SUCH DAMAGE. 3252419Sjulian */ 3352419Sjulian 3452419Sjulian#ifndef lint 3552419Sjulianstatic const char copyright[] = 3652419Sjulian"@(#) Copyright (c) 1983, 1993\n\ 3752419Sjulian The Regents of the University of California. All rights reserved.\n"; 3867506Sjulian#endif /* not lint */ 3952419Sjulian 4052419Sjulian#ifndef lint 4152752Sjulian#if 0 4252419Sjulianstatic char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 4352419Sjulian#endif 4452419Sjulianstatic const char rcsid[] = 4552419Sjulian "$FreeBSD: head/sbin/ifconfig/ifconfig.c 63473 2000-07-18 22:07:31Z archie $"; 4652419Sjulian#endif /* not lint */ 4752419Sjulian 4852419Sjulian#include <sys/param.h> 4952419Sjulian#include <sys/ioctl.h> 5052419Sjulian#include <sys/socket.h> 5152419Sjulian#include <sys/sysctl.h> 5252419Sjulian#include <sys/time.h> 5352419Sjulian#include <sys/module.h> 5452419Sjulian#include <sys/linker.h> 5552419Sjulian 5652419Sjulian#include <net/ethernet.h> 5752419Sjulian#include <net/if.h> 5852419Sjulian#include <net/if_var.h> 5952419Sjulian#include <net/if_dl.h> 6052419Sjulian#include <net/if_types.h> 6152419Sjulian#include <net/route.h> 6252419Sjulian 6352419Sjulian/* IP */ 6452419Sjulian#include <netinet/in.h> 65130413Sjulian#include <netinet/in_var.h> 6652419Sjulian#include <arpa/inet.h> 6752419Sjulian#include <netdb.h> 6852419Sjulian 6952419Sjulian/* IPX */ 7052419Sjulian#define IPXIP 7152419Sjulian#define IPTUNNEL 7252419Sjulian#include <netipx/ipx.h> 7352419Sjulian#include <netipx/ipx_if.h> 7452419Sjulian 7552419Sjulian/* Appletalk */ 7652419Sjulian#include <netatalk/at.h> 7752419Sjulian 7852419Sjulian/* XNS */ 7952419Sjulian#ifdef NS 8052419Sjulian#define NSIP 8152419Sjulian#include <netns/ns.h> 8252419Sjulian#include <netns/ns_if.h> 83130413Sjulian#endif 84130413Sjulian 85130413Sjulian/* OSI */ 86130413Sjulian 87130413Sjulian#include <ctype.h> 88130413Sjulian#include <err.h> 89130413Sjulian#include <errno.h> 90130413Sjulian#include <fcntl.h> 91130413Sjulian#include <stdio.h> 92130413Sjulian#include <stdlib.h> 93130413Sjulian#include <string.h> 94130413Sjulian#include <unistd.h> 95130413Sjulian 96130413Sjulian#include "ifconfig.h" 97130413Sjulian 98130413Sjulian/* wrapper for KAME-special getnameinfo() */ 99130413Sjulian#ifndef NI_WITHSCOPEID 100130413Sjulian#define NI_WITHSCOPEID 0 101130413Sjulian#endif 102130413Sjulian 103130413Sjulianstruct ifreq ifr, ridreq; 10452419Sjulianstruct ifaliasreq addreq; 10553407Sarchie#ifdef INET6 10652419Sjulianstruct in6_ifreq in6_ridreq; 10752419Sjulianstruct in6_aliasreq in6_addreq; 10852419Sjulian#endif 109124506Sgreenstruct sockaddr_in netmask; 110130413Sjulianstruct netrange at_nr; /* AppleTalk net range */ 11152419Sjulian 11253407Sarchiechar name[32]; 11352419Sjulianint flags; 11452419Sjulianint metric; 11552752Sjulianint mtu; 11652752Sjulianint setaddr; 11770700Sjulianint setipdst; 11852752Sjulianint doalias; 11952752Sjulianint clearaddr; 12052752Sjulianint newaddr = 1; 12152419Sjulian#ifdef INET6 122130413Sjulianstatic int ip6lifetime; 123130413Sjulian#endif 124130413Sjulian 125130413Sjulianstruct afswtch; 126130413Sjulian 127130413Sjulian#ifdef INET6 128130413Sjulianchar addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/ 129130413Sjulian#endif 130130413Sjulian 131130413Sjulianvoid Perror __P((const char *cmd)); 132130413Sjulianvoid checkatrange __P((struct sockaddr_at *)); 133130413Sjulianint ifconfig __P((int argc, char *const *argv, const struct afswtch *afp)); 134130413Sjulianvoid notealias __P((const char *, int, int, const struct afswtch *afp)); 135130413Sjulianvoid printb __P((const char *s, unsigned value, const char *bits)); 136130413Sjulianvoid rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); 137130413Sjulianvoid status __P((const struct afswtch *afp, int addrcount, 138130413Sjulian struct sockaddr_dl *sdl, struct if_msghdr *ifm, 139130413Sjulian struct ifa_msghdr *ifam)); 140130413Sjulianvoid usage __P((void)); 14152419Sjulianvoid ifmaybeload __P((char *name)); 14252419Sjulian 143129823Sjulian#ifdef INET6 144129823Sjulianint prefix __P((void *, int)); 145129823Sjulianstatic char *sec2str __P((time_t)); 146129823Sjulianint explicit_prefix = 0; 147129823Sjulian#endif 148129823Sjulian 149129823Sjuliantypedef void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp)); 150129823Sjulianc_func setatphase, setatrange; 151130413Sjulianc_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask; 15252419Sjulian#ifdef INET6 15352419Sjulianc_func setifprefixlen; 15452419Sjulianc_func setip6flags; 15552419Sjulian#endif 15652419Sjulianc_func setifipdst; 15752419Sjulianc_func setifflags, setifmetric, setifmtu, setiflladdr; 15852419Sjulian 15952419Sjulian 16052419Sjulian#define NEXTARG 0xffffff 16152419Sjulian 16252419Sjulianconst 16370700Sjulianstruct cmd { 16452419Sjulian const char *c_name; 16552419Sjulian int c_parameter; /* NEXTARG means next argv */ 16652419Sjulian void (*c_func) __P((const char *, int, int, const struct afswtch *afp)); 16752419Sjulian} cmds[] = { 168220768Sglebius { "up", IFF_UP, setifflags } , 16952419Sjulian { "down", -IFF_UP, setifflags }, 170130413Sjulian { "arp", -IFF_NOARP, setifflags }, 171130413Sjulian { "-arp", IFF_NOARP, setifflags }, 172130413Sjulian { "debug", IFF_DEBUG, setifflags }, 17370784Sjulian { "-debug", -IFF_DEBUG, setifflags }, 17452419Sjulian { "add", IFF_UP, notealias }, 17552419Sjulian { "alias", IFF_UP, notealias }, 17652419Sjulian { "-alias", -IFF_UP, notealias }, 17752419Sjulian { "delete", -IFF_UP, notealias }, 17852419Sjulian { "remove", -IFF_UP, notealias }, 17952419Sjulian#ifdef notdef 18052419Sjulian#define EN_SWABIPS 0x1000 18152419Sjulian { "swabips", EN_SWABIPS, setifflags }, 18252419Sjulian { "-swabips", -EN_SWABIPS, setifflags }, 18352419Sjulian#endif 18452419Sjulian { "netmask", NEXTARG, setifnetmask }, 18570784Sjulian#ifdef INET6 18652419Sjulian { "prefixlen", NEXTARG, setifprefixlen }, 18752419Sjulian { "anycast", IN6_IFF_ANYCAST, setip6flags }, 18852419Sjulian { "tentative", IN6_IFF_TENTATIVE, setip6flags }, 18952419Sjulian { "-tentative", -IN6_IFF_TENTATIVE, setip6flags }, 19052419Sjulian#endif 19152419Sjulian { "range", NEXTARG, setatrange }, 19252419Sjulian { "phase", NEXTARG, setatphase }, 19352419Sjulian { "metric", NEXTARG, setifmetric }, 19452419Sjulian { "broadcast", NEXTARG, setifbroadaddr }, 19552419Sjulian { "ipdst", NEXTARG, setifipdst }, 19652419Sjulian { "link0", IFF_LINK0, setifflags }, 19752419Sjulian { "-link0", -IFF_LINK0, setifflags }, 19852419Sjulian { "link1", IFF_LINK1, setifflags }, 199124506Sgreen { "-link1", -IFF_LINK1, setifflags }, 200124506Sgreen { "link2", IFF_LINK2, setifflags }, 201124506Sgreen { "-link2", -IFF_LINK2, setifflags }, 202124506Sgreen#ifdef USE_IF_MEDIA 20352419Sjulian { "media", NEXTARG, setmedia }, 20452419Sjulian { "mediaopt", NEXTARG, setmediaopt }, 20552419Sjulian { "-mediaopt", NEXTARG, unsetmediaopt }, 20652419Sjulian#endif 20752419Sjulian#ifdef USE_VLANS 20852419Sjulian { "vlan", NEXTARG, setvlantag }, 209130413Sjulian { "vlandev", NEXTARG, setvlandev }, 21052419Sjulian { "-vlandev", NEXTARG, unsetvlandev }, 21152419Sjulian#endif 21270700Sjulian { "normal", -IFF_LINK0, setifflags }, 21352419Sjulian { "compress", IFF_LINK0, setifflags }, 214130413Sjulian { "noicmp", IFF_LINK1, setifflags }, 215130413Sjulian { "mtu", NEXTARG, setifmtu }, 216130413Sjulian { "lladdr", NEXTARG, setiflladdr }, 217130413Sjulian { 0, 0, setifaddr }, 218130413Sjulian { 0, 0, setifdstaddr }, 219130413Sjulian}; 220130413Sjulian 221130413Sjulian/* 222130413Sjulian * XNS support liberally adapted from code written at the University of 223130413Sjulian * Maryland principally by James O'Toole and Chris Torek. 224130413Sjulian */ 225130413Sjuliantypedef void af_status __P((int, struct rt_addrinfo *)); 226130413Sjuliantypedef void af_getaddr __P((const char *, int)); 227130413Sjuliantypedef void af_getprefix __P((const char *, int)); 228130413Sjulian 229130413Sjulianaf_status in_status, ipx_status, at_status, ether_status; 230130413Sjulianaf_getaddr in_getaddr, ipx_getaddr, at_getaddr, ether_getaddr; 231130413Sjulian 232130413Sjulian#ifdef INET6 233130413Sjulianaf_status in6_status; 234130413Sjulianaf_getaddr in6_getaddr; 235130413Sjulianaf_getprefix in6_getprefix; 236130413Sjulian#endif /*INET6*/ 237130413Sjulian#ifdef NS 238130413Sjulianaf_status xns_status; 239130413Sjulianaf_getaddr xns_getaddr; 240130413Sjulian#endif 241130413Sjulian 242130413Sjulian/* Known address families */ 243130413Sjulianconst 244130413Sjulianstruct afswtch { 245130413Sjulian const char *af_name; 246130413Sjulian short af_af; 247130413Sjulian af_status *af_status; 248130413Sjulian af_getaddr *af_getaddr; 249130413Sjulian af_getprefix *af_getprefix; 250130413Sjulian u_long af_difaddr; 251130413Sjulian u_long af_aifaddr; 252130413Sjulian caddr_t af_ridreq; 253130413Sjulian caddr_t af_addreq; 254130413Sjulian} afs[] = { 255130413Sjulian#define C(x) ((caddr_t) &x) 256130413Sjulian { "inet", AF_INET, in_status, in_getaddr, NULL, 257130413Sjulian SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 258130413Sjulian#ifdef INET6 259130413Sjulian { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 260130413Sjulian SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 261130413Sjulian C(in6_ridreq), C(in6_addreq) }, 262130413Sjulian#endif /*INET6*/ 263130413Sjulian { "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL, 264130413Sjulian SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 265130413Sjulian { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 266130413Sjulian SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) }, 267130413Sjulian#ifdef NS 26852419Sjulian { "ns", AF_NS, xns_status, xns_getaddr, NULL, 26952419Sjulian SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 27052419Sjulian#endif 27152419Sjulian { "ether", AF_LINK, ether_status, ether_getaddr, NULL, 27252419Sjulian 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 27352419Sjulian#if 0 /* XXX conflicts with the media command */ 27452419Sjulian#ifdef USE_IF_MEDIA 27552419Sjulian { "media", AF_UNSPEC, media_status, NULL, NULL, }, /* XXX not real!! */ 27652419Sjulian#endif 277130413Sjulian#ifdef USE_VLANS 278130413Sjulian { "vlan", AF_UNSPEC, vlan_status, NULL, NULL, }, /* XXX not real!! */ 279130413Sjulian#endif 280130413Sjulian#endif 281130413Sjulian { 0, 0, 0, 0 } 282130413Sjulian}; 283130413Sjulian 284130413Sjulian/* 285130413Sjulian * Expand the compacted form of addresses as returned via the 28652419Sjulian * configuration read via sysctl(). 28752419Sjulian */ 28852419Sjulian 28952419Sjulian#define ROUNDUP(a) \ 29052419Sjulian ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 29152419Sjulian#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 29252419Sjulian 29352419Sjulianvoid 294124506Sgreenrt_xaddrs(cp, cplim, rtinfo) 295124506Sgreen caddr_t cp, cplim; 296124506Sgreen struct rt_addrinfo *rtinfo; 297130413Sjulian{ 29852419Sjulian struct sockaddr *sa; 29952419Sjulian int i; 30052419Sjulian 30152419Sjulian memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 30252419Sjulian for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 30352419Sjulian if ((rtinfo->rti_addrs & (1 << i)) == 0) 30452419Sjulian continue; 30552419Sjulian rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 30670700Sjulian ADVANCE(cp, sa); 30752419Sjulian } 30870784Sjulian} 30970784Sjulian 31052419Sjulian 31170700Sjulianvoid 31252419Sjulianusage() 31370700Sjulian{ 31452419Sjulian#ifndef INET6 31597897Sarchie fprintf(stderr, "%s\n%s\n%s\n%s\n", 31697897Sarchie "usage: ifconfig interface address_family [address [dest_address]]", 31752419Sjulian " [parameters]", 318131112Sjulian " ifconfig -a [-d] [-u] [address_family]", 319131112Sjulian " ifconfig -l [-d] [-u] [address_family]"); 32052419Sjulian#else 32197897Sarchie fprintf(stderr, "%s\n%s\n%s\n%s\n", 32252419Sjulian "usage: ifconfig [-L] interface address_family [address [dest_address]]", 323130413Sjulian " [parameters]", 324130413Sjulian " ifconfig -a [-L] [-d] [-u] [address_family]", 325130413Sjulian " ifconfig -l [-d] [-u] [address_family]"); 32652419Sjulian#endif 32752419Sjulian exit(1); 32852419Sjulian} 32952419Sjulian 33052419Sjulianint 33152419Sjulianmain(argc, argv) 33252419Sjulian int argc; 33352419Sjulian char *const *argv; 33452419Sjulian{ 33552419Sjulian int c; 33652419Sjulian int all, namesonly, downonly, uponly; 33752419Sjulian int foundit = 0, need_nl = 0; 33852419Sjulian const struct afswtch *afp = 0; 33952419Sjulian int addrcount; 34052419Sjulian struct if_msghdr *ifm, *nextifm; 341130413Sjulian struct ifa_msghdr *ifam; 34252419Sjulian struct sockaddr_dl *sdl; 34352419Sjulian char *buf, *lim, *next; 34452419Sjulian 34552419Sjulian 34670700Sjulian size_t needed; 34770700Sjulian int mib[6]; 34852419Sjulian 34952419Sjulian /* Parse leading line options */ 35052419Sjulian all = downonly = uponly = namesonly = 0; 35152419Sjulian while ((c = getopt(argc, argv, "adlmu" 35252419Sjulian#ifdef INET6 35352419Sjulian "L" 354124506Sgreen#endif 355124506Sgreen )) != -1) { 356124506Sgreen switch (c) { 357124506Sgreen case 'a': /* scan all interfaces */ 358130413Sjulian all++; 359124506Sgreen break; 360124506Sgreen#ifdef INET6 361124506Sgreen case 'L': 362124506Sgreen ip6lifetime++; /* print IPv6 address lifetime */ 363124506Sgreen break; 36452419Sjulian#endif 36552419Sjulian case 'l': /* scan interface names only */ 36652419Sjulian namesonly++; 36752419Sjulian break; 36870700Sjulian case 'd': /* restrict scan to "down" interfaces */ 36952419Sjulian downonly++; 37052419Sjulian break; 37152419Sjulian case 'u': /* restrict scan to "up" interfaces */ 37270700Sjulian uponly++; 37352419Sjulian break; 37452419Sjulian case 'm': /* show media choices in status */ 37552419Sjulian /* ignored for compatibility */ 37652419Sjulian break; 37752419Sjulian default: 37852419Sjulian usage(); 37952419Sjulian break; 38052419Sjulian } 38152419Sjulian } 38252419Sjulian argc -= optind; 38352419Sjulian argv += optind; 38470700Sjulian 38552419Sjulian /* -l cannot be used with -a or -m */ 38652419Sjulian if (namesonly && all) 38752419Sjulian usage(); 388243882Sglebius 38952419Sjulian /* nonsense.. */ 39052419Sjulian if (uponly && downonly) 39152419Sjulian usage(); 39252419Sjulian 39370700Sjulian /* no arguments is equivalent to '-a' */ 39452419Sjulian if (!namesonly && argc < 1) 395130413Sjulian all = 1; 396130413Sjulian 397243882Sglebius /* -a and -l allow an address family arg to limit the output */ 398130413Sjulian if (all || namesonly) { 399130413Sjulian if (argc > 1) 400130413Sjulian usage(); 401130413Sjulian 402130413Sjulian if (argc == 1) { 403130413Sjulian for (afp = afs; afp->af_name; afp++) 404130413Sjulian if (strcmp(afp->af_name, *argv) == 0) { 405130413Sjulian argc--, argv++; 406130413Sjulian break; 407130413Sjulian } 408130413Sjulian if (afp->af_name == NULL) 409243882Sglebius usage(); 410130413Sjulian /* leave with afp non-zero */ 411130413Sjulian } 412130413Sjulian } else { 413130413Sjulian /* not listing, need an argument */ 414130413Sjulian if (argc < 1) 415130413Sjulian usage(); 416130413Sjulian 417130413Sjulian strncpy(name, *argv, sizeof(name)); 418130413Sjulian argc--, argv++; 419130413Sjulian 420243882Sglebius /* check and maybe load support for this interface */ 421130413Sjulian ifmaybeload(name); 422130413Sjulian } 423130413Sjulian 424130413Sjulian /* Check for address family */ 425130413Sjulian if (argc > 0) { 42670700Sjulian for (afp = afs; afp->af_name; afp++) 427124506Sgreen if (strcmp(afp->af_name, *argv) == 0) { 428243882Sglebius argc--, argv++; 429124506Sgreen break; 430124506Sgreen } 431124506Sgreen if (afp->af_name == NULL) 432124506Sgreen afp = NULL; /* not a family, NULL */ 433124506Sgreen } 434124506Sgreen 435124506Sgreen mib[0] = CTL_NET; 436124506Sgreen mib[1] = PF_ROUTE; 437124506Sgreen mib[2] = 0; 438124506Sgreen mib[3] = 0; /* address family */ 439124506Sgreen mib[4] = NET_RT_IFLIST; 44052419Sjulian mib[5] = 0; 441213794Srpaulo 44252419Sjulian /* if particular family specified, only ask about it */ 44352419Sjulian if (afp) 44470700Sjulian mib[3] = afp->af_af; 44570700Sjulian 44670700Sjulian if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 44752419Sjulian errx(1, "iflist-sysctl-estimate"); 44852419Sjulian if ((buf = malloc(needed)) == NULL) 44952419Sjulian errx(1, "malloc"); 45052419Sjulian if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 45152419Sjulian errx(1, "actual retrieval of interface table"); 45252419Sjulian lim = buf + needed; 45352419Sjulian 45470700Sjulian next = buf; 45552419Sjulian while (next < lim) { 45670784Sjulian 45752419Sjulian ifm = (struct if_msghdr *)next; 45852419Sjulian 45952419Sjulian if (ifm->ifm_type == RTM_IFINFO) { 460184205Sdes sdl = (struct sockaddr_dl *)(ifm + 1); 46170784Sjulian flags = ifm->ifm_flags; 46270784Sjulian } else { 46352419Sjulian fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n"); 46452419Sjulian fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, 46552419Sjulian ifm->ifm_type); 46652419Sjulian fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); 46752419Sjulian fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, 46852419Sjulian lim); 46952419Sjulian exit (1); 47052419Sjulian } 47152419Sjulian 47270784Sjulian next += ifm->ifm_msglen; 47352419Sjulian ifam = NULL; 47470784Sjulian addrcount = 0; 47570784Sjulian while (next < lim) { 47670784Sjulian 47752419Sjulian nextifm = (struct if_msghdr *)next; 47852419Sjulian 47952419Sjulian if (nextifm->ifm_type != RTM_NEWADDR) 48052419Sjulian break; 48152419Sjulian 48252419Sjulian if (ifam == NULL) 483124506Sgreen ifam = (struct ifa_msghdr *)nextifm; 484124506Sgreen 48552419Sjulian addrcount++; 486213794Srpaulo next += nextifm->ifm_msglen; 48752419Sjulian } 48852419Sjulian 48952419Sjulian if (all || namesonly) { 490 if (uponly) 491 if ((flags & IFF_UP) == 0) 492 continue; /* not up */ 493 if (downonly) 494 if (flags & IFF_UP) 495 continue; /* not down */ 496 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 497 name[sdl->sdl_nlen] = '\0'; 498 if (namesonly) { 499 if (afp == NULL || 500 afp->af_status != ether_status || 501 sdl->sdl_type == IFT_ETHER) { 502 if (need_nl) 503 putchar(' '); 504 fputs(name, stdout); 505 need_nl++; 506 } 507 continue; 508 } 509 } else { 510 if (strlen(name) != sdl->sdl_nlen) 511 continue; /* not same len */ 512 if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) 513 continue; /* not same name */ 514 } 515 516 if (argc > 0) 517 ifconfig(argc, argv, afp); 518 else 519 status(afp, addrcount, sdl, ifm, ifam); 520 521 if (all == 0 && namesonly == 0) { 522 foundit++; /* flag it as 'done' */ 523 break; 524 } 525 } 526 free(buf); 527 528 if (namesonly && need_nl > 0) 529 putchar('\n'); 530 531 if (all == 0 && namesonly == 0 && foundit == 0) 532 errx(1, "interface %s does not exist", name); 533 534 535 exit (0); 536} 537 538 539int 540ifconfig(argc, argv, afp) 541 int argc; 542 char *const *argv; 543 const struct afswtch *afp; 544{ 545 int s; 546 547 if (afp == NULL) 548 afp = &afs[0]; 549 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 550 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 551 552 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 553 err(1, "socket"); 554 555 while (argc > 0) { 556 register const struct cmd *p; 557 558 for (p = cmds; p->c_name; p++) 559 if (strcmp(*argv, p->c_name) == 0) 560 break; 561 if (p->c_name == 0 && setaddr) 562 p++; /* got src, do dst */ 563 if (p->c_func) { 564 if (p->c_parameter == NEXTARG) { 565 if (argv[1] == NULL) 566 errx(1, "'%s' requires argument", 567 p->c_name); 568 (*p->c_func)(argv[1], 0, s, afp); 569 argc--, argv++; 570 } else 571 (*p->c_func)(*argv, p->c_parameter, s, afp); 572 } 573 argc--, argv++; 574 } 575#ifdef INET6 576 if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) { 577 /* Aggregatable address architecture defines all prefixes 578 are 64. So, it is convenient to set prefixlen to 64 if 579 it is not specified. */ 580 setifprefixlen("64", 0, s, afp); 581 /* in6_getprefix("64", MASK) if MASK is available here... */ 582 } 583#endif 584 if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) { 585 struct ipxip_req rq; 586 int size = sizeof(rq); 587 588 rq.rq_ipx = addreq.ifra_addr; 589 rq.rq_ip = addreq.ifra_dstaddr; 590 591 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 592 Perror("Encapsulation Routing"); 593 } 594 if (ifr.ifr_addr.sa_family == AF_APPLETALK) 595 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 596#ifdef NS 597 if (setipdst && ifr.ifr_addr.sa_family == AF_NS) { 598 struct nsip_req rq; 599 int size = sizeof(rq); 600 601 rq.rq_ns = addreq.ifra_addr; 602 rq.rq_ip = addreq.ifra_dstaddr; 603 604 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 605 Perror("Encapsulation Routing"); 606 } 607#endif 608 if (clearaddr) { 609 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 610 warnx("interface %s cannot change %s addresses!", 611 name, afp->af_name); 612 clearaddr = NULL; 613 } 614 } 615 if (clearaddr) { 616 int ret; 617 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 618 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { 619 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 620 /* means no previous address for interface */ 621 } else 622 Perror("ioctl (SIOCDIFADDR)"); 623 } 624 } 625 if (newaddr) { 626 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 627 warnx("interface %s cannot change %s addresses!", 628 name, afp->af_name); 629 newaddr = 0; 630 } 631 } 632 if (newaddr) { 633 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 634 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 635 Perror("ioctl (SIOCAIFADDR)"); 636 } 637 close(s); 638 return(0); 639} 640#define RIDADDR 0 641#define ADDR 1 642#define MASK 2 643#define DSTADDR 3 644 645/*ARGSUSED*/ 646void 647setifaddr(addr, param, s, afp) 648 const char *addr; 649 int param; 650 int s; 651 const struct afswtch *afp; 652{ 653 if (*afp->af_getaddr == NULL) 654 return; 655 /* 656 * Delay the ioctl to set the interface addr until flags are all set. 657 * The address interpretation may depend on the flags, 658 * and the flags may change when the address is set. 659 */ 660 setaddr++; 661 if (doalias == 0 && afp->af_af != AF_LINK) 662 clearaddr = 1; 663 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 664} 665 666void 667setifnetmask(addr, dummy, s, afp) 668 const char *addr; 669 int dummy __unused; 670 int s; 671 const struct afswtch *afp; 672{ 673 if (*afp->af_getaddr == NULL) 674 return; 675 (*afp->af_getaddr)(addr, MASK); 676} 677 678#ifdef INET6 679void 680setifprefixlen(addr, dummy, s, afp) 681 const char *addr; 682 int dummy __unused; 683 int s; 684 const struct afswtch *afp; 685{ 686 if (*afp->af_getprefix) 687 (*afp->af_getprefix)(addr, MASK); 688 explicit_prefix = 1; 689} 690 691void 692setip6flags(dummyaddr, flag, dummysoc, afp) 693 const char *dummyaddr __unused; 694 int flag; 695 int dummysoc __unused; 696 const struct afswtch *afp; 697{ 698 if (afp->af_af != AF_INET6) 699 err(1, "address flags can be set only for inet6 addresses"); 700 701 if (flag < 0) 702 in6_addreq.ifra_flags &= ~(-flag); 703 else 704 in6_addreq.ifra_flags |= flag; 705} 706#endif 707 708void 709setifbroadaddr(addr, dummy, s, afp) 710 const char *addr; 711 int dummy __unused; 712 int s; 713 const struct afswtch *afp; 714{ 715 if (*afp->af_getaddr == NULL) 716 return; 717 (*afp->af_getaddr)(addr, DSTADDR); 718} 719 720void 721setifipdst(addr, dummy, s, afp) 722 const char *addr; 723 int dummy __unused; 724 int s; 725 const struct afswtch *afp; 726{ 727 in_getaddr(addr, DSTADDR); 728 setipdst++; 729 clearaddr = 0; 730 newaddr = 0; 731} 732#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 733 734void 735notealias(addr, param, s, afp) 736 const char *addr; 737 int param; 738 int s; 739 const struct afswtch *afp; 740{ 741 if (setaddr && doalias == 0 && param < 0) 742 bcopy((caddr_t)rqtosa(af_addreq), 743 (caddr_t)rqtosa(af_ridreq), 744 rqtosa(af_addreq)->sa_len); 745 doalias = param; 746 if (param < 0) { 747 clearaddr = 1; 748 newaddr = 0; 749 } else 750 clearaddr = 0; 751} 752 753/*ARGSUSED*/ 754void 755setifdstaddr(addr, param, s, afp) 756 const char *addr; 757 int param __unused; 758 int s; 759 const struct afswtch *afp; 760{ 761 if (*afp->af_getaddr == NULL) 762 return; 763 (*afp->af_getaddr)(addr, DSTADDR); 764} 765 766/* 767 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 768 * of the ifreq structure, which may confuse other parts of ifconfig. 769 * Make a private copy so we can avoid that. 770 */ 771void 772setifflags(vname, value, s, afp) 773 const char *vname; 774 int value; 775 int s; 776 const struct afswtch *afp; 777{ 778 struct ifreq my_ifr; 779 780 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 781 782 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 783 Perror("ioctl (SIOCGIFFLAGS)"); 784 exit(1); 785 } 786 strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name)); 787 flags = my_ifr.ifr_flags; 788 789 if (value < 0) { 790 value = -value; 791 flags &= ~value; 792 } else 793 flags |= value; 794 my_ifr.ifr_flags = flags; 795 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 796 Perror(vname); 797} 798 799void 800setifmetric(val, dummy, s, afp) 801 const char *val; 802 int dummy __unused; 803 int s; 804 const struct afswtch *afp; 805{ 806 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 807 ifr.ifr_metric = atoi(val); 808 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 809 warn("ioctl (set metric)"); 810} 811 812void 813setifmtu(val, dummy, s, afp) 814 const char *val; 815 int dummy __unused; 816 int s; 817 const struct afswtch *afp; 818{ 819 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 820 ifr.ifr_mtu = atoi(val); 821 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 822 warn("ioctl (set mtu)"); 823} 824 825void 826setiflladdr(val, dummy, s, afp) 827 const char *val; 828 int dummy __unused; 829 int s; 830 const struct afswtch *afp; 831{ 832 struct ether_addr *ea; 833 834 ea = ether_aton(val); 835 if (ea == NULL) { 836 warn("malformed link-level address"); 837 return; 838 } 839 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 840 ifr.ifr_addr.sa_len = ETHER_ADDR_LEN; 841 ifr.ifr_addr.sa_family = AF_LINK; 842 bcopy(ea, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN); 843 if (ioctl(s, SIOCSIFLLADDR, (caddr_t)&ifr) < 0) 844 warn("ioctl (set lladdr)"); 845 846 return; 847} 848 849#define IFFBITS \ 850"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 851"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 852"\20MULTICAST" 853 854/* 855 * Print the status of the interface. If an address family was 856 * specified, show it and it only; otherwise, show them all. 857 */ 858void 859status(afp, addrcount, sdl, ifm, ifam) 860 const struct afswtch *afp; 861 int addrcount; 862 struct sockaddr_dl *sdl; 863 struct if_msghdr *ifm; 864 struct ifa_msghdr *ifam; 865{ 866 const struct afswtch *p = NULL; 867 struct rt_addrinfo info; 868 int allfamilies, s; 869 struct ifstat ifs; 870 871 if (afp == NULL) { 872 allfamilies = 1; 873 afp = &afs[0]; 874 } else 875 allfamilies = 0; 876 877 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 878 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 879 880 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 881 err(1, "socket"); 882 883 /* 884 * XXX is it we are doing a SIOCGIFMETRIC etc for one family. 885 * is it possible that the metric and mtu can be different for 886 * each family? If so, we have a format problem, because the 887 * metric and mtu is printed on the global the flags line. 888 */ 889 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) 890 warn("ioctl (SIOCGIFMETRIC)"); 891 else 892 metric = ifr.ifr_metric; 893 894 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) 895 warn("ioctl (SIOCGIFMTU)"); 896 else 897 mtu = ifr.ifr_mtu; 898 899 printf("%s: ", name); 900 printb("flags", flags, IFFBITS); 901 if (metric) 902 printf(" metric %d", metric); 903 if (mtu) 904 printf(" mtu %d", mtu); 905 putchar('\n'); 906 907 while (addrcount > 0) { 908 909 info.rti_addrs = ifam->ifam_addrs; 910 911 /* Expand the compacted addresses */ 912 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 913 &info); 914 915 if (!allfamilies) { 916 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family) { 917 p = afp; 918 (*p->af_status)(s, &info); 919 } 920 } else for (p = afs; p->af_name; p++) { 921 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family) 922 (*p->af_status)(s, &info); 923 } 924 addrcount--; 925 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); 926 } 927 if (allfamilies || afp->af_status == ether_status) 928 ether_status(s, (struct rt_addrinfo *)sdl); 929#ifdef USE_IF_MEDIA 930 if (allfamilies || afp->af_status == media_status) 931 media_status(s, NULL); 932#endif 933#ifdef USE_VLANS 934 if (allfamilies || afp->af_status == vlan_status) 935 vlan_status(s, NULL); 936#endif 937 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 938 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 939 printf("%s", ifs.ascii); 940 941 if (!allfamilies && !p && afp->af_status != media_status && 942 afp->af_status != ether_status && afp->af_status != vlan_status) 943 warnx("%s has no %s interface address!", name, afp->af_name); 944 945 close(s); 946 return; 947} 948 949void 950in_status(s, info) 951 int s __unused; 952 struct rt_addrinfo * info; 953{ 954 struct sockaddr_in *sin, null_sin; 955 956 memset(&null_sin, 0, sizeof(null_sin)); 957 958 sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; 959 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 960 961 if (flags & IFF_POINTOPOINT) { 962 /* note RTAX_BRD overlap with IFF_BROADCAST */ 963 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 964 if (!sin) 965 sin = &null_sin; 966 printf("--> %s ", inet_ntoa(sin->sin_addr)); 967 } 968 969 sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; 970 if (!sin) 971 sin = &null_sin; 972 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 973 974 if (flags & IFF_BROADCAST) { 975 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 976 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 977 if (sin && sin->sin_addr.s_addr != 0) 978 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 979 } 980 putchar('\n'); 981} 982 983#ifdef INET6 984void 985in6_status(s, info) 986 int s __unused; 987 struct rt_addrinfo * info; 988{ 989 struct sockaddr_in6 *sin, null_sin; 990 struct in6_ifreq ifr6; 991 int s6; 992 u_int32_t flags6; 993 struct in6_addrlifetime lifetime; 994 time_t t = time(NULL); 995 int error; 996 u_int32_t scopeid; 997 998 memset(&null_sin, 0, sizeof(null_sin)); 999 1000 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA]; 1001 strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); 1002 if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1003 perror("ifconfig: socket"); 1004 return; 1005 } 1006 ifr6.ifr_addr = *sin; 1007 if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 1008 perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)"); 1009 close(s6); 1010 return; 1011 } 1012 flags6 = ifr6.ifr_ifru.ifru_flags6; 1013 memset(&lifetime, 0, sizeof(lifetime)); 1014 ifr6.ifr_addr = *sin; 1015 if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) { 1016 perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)"); 1017 close(s6); 1018 return; 1019 } 1020 lifetime = ifr6.ifr_ifru.ifru_lifetime; 1021 close(s6); 1022 1023 /* XXX: embedded link local addr check */ 1024 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1025 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1026 u_short index; 1027 1028 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1029 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1030 if (sin->sin6_scope_id == 0) 1031 sin->sin6_scope_id = ntohs(index); 1032 } 1033 scopeid = sin->sin6_scope_id; 1034 1035 error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, 1036 sizeof(addr_buf), NULL, 0, 1037 NI_NUMERICHOST|NI_WITHSCOPEID); 1038 if (error != 0) 1039 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1040 sizeof(addr_buf)); 1041 printf("\tinet6 %s ", addr_buf); 1042 1043 if (flags & IFF_POINTOPOINT) { 1044 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1045 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD]; 1046 /* 1047 * some of the interfaces do not have valid destination 1048 * address. 1049 */ 1050 if (sin && sin->sin6_family == AF_INET6) { 1051 int error; 1052 1053 /* XXX: embedded link local addr check */ 1054 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1055 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1056 u_short index; 1057 1058 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1059 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1060 if (sin->sin6_scope_id == 0) 1061 sin->sin6_scope_id = ntohs(index); 1062 } 1063 1064 error = getnameinfo((struct sockaddr *)sin, 1065 sin->sin6_len, addr_buf, 1066 sizeof(addr_buf), NULL, 0, 1067 NI_NUMERICHOST|NI_WITHSCOPEID); 1068 if (error != 0) 1069 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1070 sizeof(addr_buf)); 1071 printf("--> %s ", addr_buf); 1072 } 1073 } 1074 1075 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; 1076 if (!sin) 1077 sin = &null_sin; 1078 printf("prefixlen %d ", prefix(&sin->sin6_addr, 1079 sizeof(struct in6_addr))); 1080 1081 if (flags6 & IN6_IFF_ANYCAST) 1082 printf("anycast "); 1083 if (flags6 & IN6_IFF_TENTATIVE) 1084 printf("tentative "); 1085 if (flags6 & IN6_IFF_DUPLICATED) 1086 printf("duplicated "); 1087 if (flags6 & IN6_IFF_DETACHED) 1088 printf("detached "); 1089 if (flags6 & IN6_IFF_DEPRECATED) 1090 printf("deprecated "); 1091 1092 if (scopeid) 1093 printf("scopeid 0x%x ", scopeid); 1094 1095 if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { 1096 printf("pltime "); 1097 if (lifetime.ia6t_preferred) { 1098 printf("%s ", lifetime.ia6t_preferred < t 1099 ? "0" : sec2str(lifetime.ia6t_preferred - t)); 1100 } else 1101 printf("infty "); 1102 1103 printf("vltime "); 1104 if (lifetime.ia6t_expire) { 1105 printf("%s ", lifetime.ia6t_expire < t 1106 ? "0" : sec2str(lifetime.ia6t_expire - t)); 1107 } else 1108 printf("infty "); 1109 } 1110 1111 putchar('\n'); 1112} 1113#endif /*INET6*/ 1114 1115void 1116ipx_status(s, info) 1117 int s __unused; 1118 struct rt_addrinfo * info; 1119{ 1120 struct sockaddr_ipx *sipx, null_sipx; 1121 1122 memset(&null_sipx, 0, sizeof(null_sipx)); 1123 1124 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA]; 1125 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 1126 1127 if (flags & IFF_POINTOPOINT) { 1128 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD]; 1129 if (!sipx) 1130 sipx = &null_sipx; 1131 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 1132 } 1133 putchar('\n'); 1134} 1135 1136void 1137at_status(s, info) 1138 int s __unused; 1139 struct rt_addrinfo * info; 1140{ 1141 struct sockaddr_at *sat, null_sat; 1142 struct netrange *nr; 1143 1144 memset(&null_sat, 0, sizeof(null_sat)); 1145 1146 sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA]; 1147 nr = &sat->sat_range.r_netrange; 1148 printf("\tatalk %d.%d range %d-%d phase %d", 1149 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1150 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 1151 if (flags & IFF_POINTOPOINT) { 1152 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1153 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1154 if (!sat) 1155 sat = &null_sat; 1156 printf("--> %d.%d", 1157 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 1158 } 1159 if (flags & IFF_BROADCAST) { 1160 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1161 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1162 if (sat) 1163 printf(" broadcast %d.%d", 1164 ntohs(sat->sat_addr.s_net), 1165 sat->sat_addr.s_node); 1166 } 1167 1168 putchar('\n'); 1169} 1170 1171#ifdef NS 1172void 1173xns_status(s, info) 1174 int s __unused; 1175 struct rt_addrinfo * info; 1176{ 1177 struct sockaddr_ns *sns, null_sns; 1178 1179 memset(&null_sns, 0, sizeof(null_sns)); 1180 1181 sns = (struct sockaddr_ns *)info->rti_info[RTAX_IFA]; 1182 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1183 1184 if (flags & IFF_POINTOPOINT) { 1185 sns = (struct sockaddr_ns *)info->rti_info[RTAX_BRD]; 1186 if (!sns) 1187 sns = &null_sns; 1188 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1189 } 1190 1191 putchar('\n'); 1192 close(s); 1193} 1194#endif 1195 1196 1197void 1198ether_status(s, info) 1199 int s __unused; 1200 struct rt_addrinfo *info; 1201{ 1202 char *cp; 1203 int n; 1204 struct sockaddr_dl *sdl = (struct sockaddr_dl *)info; 1205 1206 cp = (char *)LLADDR(sdl); 1207 if ((n = sdl->sdl_alen) > 0) { 1208 if (sdl->sdl_type == IFT_ETHER) 1209 printf ("\tether "); 1210 else 1211 printf ("\tlladdr "); 1212 while (--n >= 0) 1213 printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' '); 1214 putchar('\n'); 1215 } 1216} 1217 1218void 1219Perror(cmd) 1220 const char *cmd; 1221{ 1222 switch (errno) { 1223 1224 case ENXIO: 1225 errx(1, "%s: no such interface", cmd); 1226 break; 1227 1228 case EPERM: 1229 errx(1, "%s: permission denied", cmd); 1230 break; 1231 1232 default: 1233 err(1, "%s", cmd); 1234 } 1235} 1236 1237#define SIN(x) ((struct sockaddr_in *) &(x)) 1238struct sockaddr_in *sintab[] = { 1239SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1240SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1241 1242void 1243in_getaddr(s, which) 1244 const char *s; 1245 int which; 1246{ 1247 register struct sockaddr_in *sin = sintab[which]; 1248 struct hostent *hp; 1249 struct netent *np; 1250 1251 sin->sin_len = sizeof(*sin); 1252 if (which != MASK) 1253 sin->sin_family = AF_INET; 1254 1255 if (inet_aton(s, &sin->sin_addr)) 1256 return; 1257 if ((hp = gethostbyname(s)) != 0) 1258 bcopy(hp->h_addr, (char *)&sin->sin_addr, 1259 MIN(hp->h_length, sizeof(sin->sin_addr))); 1260 else if ((np = getnetbyname(s)) != 0) 1261 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1262 else 1263 errx(1, "%s: bad value", s); 1264} 1265 1266#ifdef INET6 1267#define SIN6(x) ((struct sockaddr_in6 *) &(x)) 1268struct sockaddr_in6 *sin6tab[] = { 1269SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 1270SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 1271 1272void 1273in6_getaddr(s, which) 1274 const char *s; 1275 int which; 1276{ 1277 register struct sockaddr_in6 *sin = sin6tab[which]; 1278 struct addrinfo hints, *res; 1279 int error = -1; 1280 1281 newaddr &= 1; 1282 1283 sin->sin6_len = sizeof(*sin); 1284 if (which != MASK) 1285 sin->sin6_family = AF_INET6; 1286 1287 if (sin->sin6_family == AF_INET6) { 1288 bzero(&hints, sizeof(struct addrinfo)); 1289 hints.ai_family = AF_INET6; 1290 error = getaddrinfo(s, NULL, &hints, &res); 1291 } 1292 if (error != 0) { 1293 if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) 1294 errx(1, "%s: bad value", s); 1295 } else 1296 bcopy(res->ai_addr, sin, res->ai_addrlen); 1297} 1298 1299void 1300in6_getprefix(plen, which) 1301 const char *plen; 1302 int which; 1303{ 1304 register struct sockaddr_in6 *sin = sin6tab[which]; 1305 register u_char *cp; 1306 int len = atoi(plen); 1307 1308 if ((len < 0) || (len > 128)) 1309 errx(1, "%s: bad value", plen); 1310 sin->sin6_len = sizeof(*sin); 1311 if (which != MASK) 1312 sin->sin6_family = AF_INET6; 1313 if ((len == 0) || (len == 128)) { 1314 memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); 1315 return; 1316 } 1317 memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); 1318 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 1319 *cp++ = 0xff; 1320 *cp = 0xff << (8 - len); 1321} 1322#endif 1323 1324/* 1325 * Print a value a la the %b format of the kernel's printf 1326 */ 1327void 1328printb(s, v, bits) 1329 const char *s; 1330 register unsigned v; 1331 register const char *bits; 1332{ 1333 register int i, any = 0; 1334 register char c; 1335 1336 if (bits && *bits == 8) 1337 printf("%s=%o", s, v); 1338 else 1339 printf("%s=%x", s, v); 1340 bits++; 1341 if (bits) { 1342 putchar('<'); 1343 while ((i = *bits++) != '\0') { 1344 if (v & (1 << (i-1))) { 1345 if (any) 1346 putchar(','); 1347 any = 1; 1348 for (; (c = *bits) > 32; bits++) 1349 putchar(c); 1350 } else 1351 for (; *bits > 32; bits++) 1352 ; 1353 } 1354 putchar('>'); 1355 } 1356} 1357 1358#define SIPX(x) ((struct sockaddr_ipx *) &(x)) 1359struct sockaddr_ipx *sipxtab[] = { 1360SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 1361SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 1362 1363void 1364ipx_getaddr(addr, which) 1365 const char *addr; 1366 int which; 1367{ 1368 struct sockaddr_ipx *sipx = sipxtab[which]; 1369 1370 sipx->sipx_family = AF_IPX; 1371 sipx->sipx_len = sizeof(*sipx); 1372 sipx->sipx_addr = ipx_addr(addr); 1373 if (which == MASK) 1374 printf("Attempt to set IPX netmask will be ineffectual\n"); 1375} 1376 1377void 1378at_getaddr(addr, which) 1379 const char *addr; 1380 int which; 1381{ 1382 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 1383 u_int net, node; 1384 1385 sat->sat_family = AF_APPLETALK; 1386 sat->sat_len = sizeof(*sat); 1387 if (which == MASK) 1388 errx(1, "AppleTalk does not use netmasks"); 1389 if (sscanf(addr, "%u.%u", &net, &node) != 2 1390 || net > 0xffff || node > 0xfe) 1391 errx(1, "%s: illegal address", addr); 1392 sat->sat_addr.s_net = htons(net); 1393 sat->sat_addr.s_node = node; 1394} 1395 1396void 1397ether_getaddr(addr, which) 1398 const char *addr; 1399 int which; 1400{ 1401 struct ether_addr *ea; 1402 struct sockaddr *sea = &ridreq.ifr_addr; 1403 1404 ea = ether_aton(addr); 1405 if (ea == NULL) 1406 errx(1, "malformed ether address"); 1407 if (which == MASK) 1408 errx(1, "Ethernet does not use netmasks"); 1409 sea->sa_family = AF_LINK; 1410 sea->sa_len = ETHER_ADDR_LEN; 1411 bcopy(ea, sea->sa_data, ETHER_ADDR_LEN); 1412} 1413 1414/* XXX FIXME -- should use strtoul for better parsing. */ 1415void 1416setatrange(range, dummy, s, afp) 1417 const char *range; 1418 int dummy __unused; 1419 int s; 1420 const struct afswtch *afp; 1421{ 1422 u_short first = 123, last = 123; 1423 1424 if (sscanf(range, "%hu-%hu", &first, &last) != 2 1425 || first == 0 || first > 0xffff 1426 || last == 0 || last > 0xffff || first > last) 1427 errx(1, "%s: illegal net range: %u-%u", range, first, last); 1428 at_nr.nr_firstnet = htons(first); 1429 at_nr.nr_lastnet = htons(last); 1430} 1431 1432void 1433setatphase(phase, dummy, s, afp) 1434 const char *phase; 1435 int dummy __unused; 1436 int s; 1437 const struct afswtch *afp; 1438{ 1439 if (!strcmp(phase, "1")) 1440 at_nr.nr_phase = 1; 1441 else if (!strcmp(phase, "2")) 1442 at_nr.nr_phase = 2; 1443 else 1444 errx(1, "%s: illegal phase", phase); 1445} 1446 1447void 1448checkatrange(struct sockaddr_at *sat) 1449{ 1450 if (at_nr.nr_phase == 0) 1451 at_nr.nr_phase = 2; /* Default phase 2 */ 1452 if (at_nr.nr_firstnet == 0) 1453 at_nr.nr_firstnet = /* Default range of one */ 1454 at_nr.nr_lastnet = sat->sat_addr.s_net; 1455printf("\tatalk %d.%d range %d-%d phase %d\n", 1456 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1457 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 1458 if ((u_short) ntohs(at_nr.nr_firstnet) > 1459 (u_short) ntohs(sat->sat_addr.s_net) 1460 || (u_short) ntohs(at_nr.nr_lastnet) < 1461 (u_short) ntohs(sat->sat_addr.s_net)) 1462 errx(1, "AppleTalk address is not in range"); 1463 sat->sat_range.r_netrange = at_nr; 1464} 1465 1466#ifdef NS 1467#define SNS(x) ((struct sockaddr_ns *) &(x)) 1468struct sockaddr_ns *snstab[] = { 1469SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 1470SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 1471 1472void 1473xns_getaddr(addr, which) 1474 const char *addr; 1475 int which; 1476{ 1477 struct sockaddr_ns *sns = snstab[which]; 1478 1479 sns->sns_family = AF_NS; 1480 sns->sns_len = sizeof(*sns); 1481 sns->sns_addr = ns_addr(addr); 1482 if (which == MASK) 1483 printf("Attempt to set XNS netmask will be ineffectual\n"); 1484} 1485#endif 1486 1487#ifdef INET6 1488int 1489prefix(val, size) 1490 void *val; 1491 int size; 1492{ 1493 register u_char *name = (u_char *)val; 1494 register int byte, bit, plen = 0; 1495 1496 for (byte = 0; byte < size; byte++, plen += 8) 1497 if (name[byte] != 0xff) 1498 break; 1499 if (byte == size) 1500 return (plen); 1501 for (bit = 7; bit != 0; bit--, plen++) 1502 if (!(name[byte] & (1 << bit))) 1503 break; 1504 for (; bit != 0; bit--) 1505 if (name[byte] & (1 << bit)) 1506 return(0); 1507 byte++; 1508 for (; byte < size; byte++) 1509 if (name[byte]) 1510 return(0); 1511 return (plen); 1512} 1513 1514static char * 1515sec2str(total) 1516 time_t total; 1517{ 1518 static char result[256]; 1519 int days, hours, mins, secs; 1520 int first = 1; 1521 char *p = result; 1522 1523 if (0) { 1524 days = total / 3600 / 24; 1525 hours = (total / 3600) % 24; 1526 mins = (total / 60) % 60; 1527 secs = total % 60; 1528 1529 if (days) { 1530 first = 0; 1531 p += sprintf(p, "%dd", days); 1532 } 1533 if (!first || hours) { 1534 first = 0; 1535 p += sprintf(p, "%dh", hours); 1536 } 1537 if (!first || mins) { 1538 first = 0; 1539 p += sprintf(p, "%dm", mins); 1540 } 1541 sprintf(p, "%ds", secs); 1542 } else 1543 sprintf(result, "%lu", (unsigned long)total); 1544 1545 return(result); 1546} 1547#endif /*INET6*/ 1548 1549void 1550ifmaybeload(name) 1551 char *name; 1552{ 1553 struct module_stat mstat; 1554 int fileid, modid; 1555 char ifkind[35], *cp, *dp; 1556 1557 1558 /* turn interface and unit into module name */ 1559 strcpy(ifkind, "if_"); 1560 for (cp = name, dp = ifkind + 3; (*cp != 0) && !isdigit(*cp); cp++, dp++) 1561 *dp = *cp; 1562 *dp = 0; 1563 1564 /* scan files in kernel */ 1565 mstat.version = sizeof(struct module_stat); 1566 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1567 /* scan modules in file */ 1568 for (modid = kldfirstmod(fileid); modid > 0; 1569 modid = modfnext(modid)) { 1570 if (modstat(modid, &mstat) < 0) 1571 continue; 1572 /* strip bus name if present */ 1573 if ((cp = strchr(mstat.name, '/')) != NULL) { 1574 cp++; 1575 } else { 1576 cp = mstat.name; 1577 } 1578 /* already loaded? */ 1579 if (!strcmp(ifkind, cp)) 1580 return; 1581 } 1582 } 1583 1584 /* not present, we should try to load it */ 1585 kldload(ifkind); 1586} 1587