ifconfig.c revision 179894
1145516Sdarrenr/* 2145516Sdarrenr * Copyright (c) 1983, 1993 3145516Sdarrenr * The Regents of the University of California. All rights reserved. 4145516Sdarrenr * 5145516Sdarrenr * Redistribution and use in source and binary forms, with or without 6145516Sdarrenr * modification, are permitted provided that the following conditions 7145516Sdarrenr * are met: 8145516Sdarrenr * 1. Redistributions of source code must retain the above copyright 9145516Sdarrenr * notice, this list of conditions and the following disclaimer. 10145516Sdarrenr * 2. Redistributions in binary form must reproduce the above copyright 11145516Sdarrenr * notice, this list of conditions and the following disclaimer in the 12145516Sdarrenr * documentation and/or other materials provided with the distribution. 13145516Sdarrenr * 4. Neither the name of the University nor the names of its contributors 14145516Sdarrenr * may be used to endorse or promote products derived from this software 15145516Sdarrenr * without specific prior written permission. 16145516Sdarrenr * 17145516Sdarrenr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18145516Sdarrenr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19145516Sdarrenr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20145516Sdarrenr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21145516Sdarrenr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22145516Sdarrenr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23145516Sdarrenr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24145516Sdarrenr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25145516Sdarrenr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26145516Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27145516Sdarrenr * SUCH DAMAGE. 28145516Sdarrenr */ 29145516Sdarrenr 30145516Sdarrenr#ifndef lint 31145516Sdarrenrstatic const char copyright[] = 32145516Sdarrenr"@(#) Copyright (c) 1983, 1993\n\ 33145516Sdarrenr The Regents of the University of California. All rights reserved.\n"; 34145516Sdarrenr#endif /* not lint */ 35145516Sdarrenr 36145516Sdarrenr#ifndef lint 37145516Sdarrenr#if 0 38145516Sdarrenrstatic char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 39145516Sdarrenr#endif 40145516Sdarrenrstatic const char rcsid[] = 41145516Sdarrenr "$FreeBSD: head/sbin/ifconfig/ifconfig.c 179894 2008-06-20 17:26:34Z thompsa $"; 42145516Sdarrenr#endif /* not lint */ 43145516Sdarrenr 44145516Sdarrenr#include <sys/param.h> 45145516Sdarrenr#include <sys/ioctl.h> 46145516Sdarrenr#include <sys/socket.h> 47145516Sdarrenr#include <sys/sysctl.h> 48145516Sdarrenr#include <sys/time.h> 49145516Sdarrenr#include <sys/module.h> 50145516Sdarrenr#include <sys/linker.h> 51145516Sdarrenr 52145516Sdarrenr#include <net/ethernet.h> 53145516Sdarrenr#include <net/if.h> 54145516Sdarrenr#include <net/if_gre.h> 55145516Sdarrenr#include <net/if_var.h> 56145516Sdarrenr#include <net/if_dl.h> 57145516Sdarrenr#include <net/if_types.h> 58145516Sdarrenr#include <net/route.h> 59145516Sdarrenr 60145516Sdarrenr/* IP */ 61145516Sdarrenr#include <netinet/in.h> 62145516Sdarrenr#include <netinet/in_var.h> 63145516Sdarrenr#include <arpa/inet.h> 64145516Sdarrenr#include <netdb.h> 65145516Sdarrenr 66145516Sdarrenr#include <ifaddrs.h> 67145516Sdarrenr#include <ctype.h> 68145516Sdarrenr#include <err.h> 69145516Sdarrenr#include <errno.h> 70145516Sdarrenr#include <fcntl.h> 71145516Sdarrenr#include <stdio.h> 72145516Sdarrenr#include <stdlib.h> 73145516Sdarrenr#include <string.h> 74145516Sdarrenr#include <unistd.h> 75145516Sdarrenr 76145516Sdarrenr#include "ifconfig.h" 77145516Sdarrenr 78145516Sdarrenr/* 79145516Sdarrenr * Since "struct ifreq" is composed of various union members, callers 80145516Sdarrenr * should pay special attention to interprete the value. 81145516Sdarrenr * (.e.g. little/big endian difference in the structure.) 82145516Sdarrenr */ 83145516Sdarrenrstruct ifreq ifr; 84145516Sdarrenr 85145516Sdarrenrchar name[IFNAMSIZ]; 86145516Sdarrenrint setaddr; 87145516Sdarrenrint setmask; 88145516Sdarrenrint doalias; 89145516Sdarrenrint clearaddr; 90145516Sdarrenrint newaddr = 1; 91145516Sdarrenrint verbose; 92145516Sdarrenrint noload; 93145516Sdarrenr 94145516Sdarrenrint supmedia = 0; 95145516Sdarrenrint printkeys = 0; /* Print keying material for interfaces. */ 96145516Sdarrenr 97145516Sdarrenrstatic int ifconfig(int argc, char *const *argv, int iscreate, 98145516Sdarrenr const struct afswtch *afp); 99145516Sdarrenrstatic void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 100145516Sdarrenr struct ifaddrs *ifa); 101145516Sdarrenrstatic void tunnel_status(int s); 102145516Sdarrenrstatic void usage(void); 103145516Sdarrenr 104145516Sdarrenrstatic struct afswtch *af_getbyname(const char *name); 105145516Sdarrenrstatic struct afswtch *af_getbyfamily(int af); 106145516Sdarrenrstatic void af_other_status(int); 107145516Sdarrenr 108145516Sdarrenrstatic struct option *opts = NULL; 109145516Sdarrenr 110145516Sdarrenrvoid 111145516Sdarrenropt_register(struct option *p) 112145516Sdarrenr{ 113145516Sdarrenr p->next = opts; 114145516Sdarrenr opts = p; 115145516Sdarrenr} 116145516Sdarrenr 117145516Sdarrenrstatic void 118145516Sdarrenrusage(void) 119145516Sdarrenr{ 120145516Sdarrenr char options[1024]; 121145516Sdarrenr struct option *p; 122145516Sdarrenr 123145516Sdarrenr /* XXX not right but close enough for now */ 124145516Sdarrenr options[0] = '\0'; 125145516Sdarrenr for (p = opts; p != NULL; p = p->next) { 126145516Sdarrenr strlcat(options, p->opt_usage, sizeof(options)); 127145516Sdarrenr strlcat(options, " ", sizeof(options)); 128145516Sdarrenr } 129145516Sdarrenr 130145516Sdarrenr fprintf(stderr, 131145516Sdarrenr "usage: ifconfig %sinterface address_family [address [dest_address]]\n" 132145516Sdarrenr " [parameters]\n" 133145516Sdarrenr " ifconfig interface create\n" 134145516Sdarrenr " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n" 135145516Sdarrenr " ifconfig -l [-d] [-u] [address_family]\n" 136145516Sdarrenr " ifconfig %s[-d] [-m] [-u] [-v]\n", 137145516Sdarrenr options, options, options); 138145516Sdarrenr exit(1); 139145516Sdarrenr} 140145516Sdarrenr 141145516Sdarrenrint 142145516Sdarrenrmain(int argc, char *argv[]) 143145516Sdarrenr{ 144145516Sdarrenr int c, all, namesonly, downonly, uponly; 145145516Sdarrenr const struct afswtch *afp = NULL; 146145516Sdarrenr int ifindex; 147145516Sdarrenr struct ifaddrs *ifap, *ifa; 148145516Sdarrenr struct ifreq paifr; 149145516Sdarrenr const struct sockaddr_dl *sdl; 150145516Sdarrenr char options[1024], *cp; 151145516Sdarrenr const char *ifname; 152145516Sdarrenr struct option *p; 153145516Sdarrenr size_t iflen; 154145516Sdarrenr 155145516Sdarrenr all = downonly = uponly = namesonly = noload = verbose = 0; 156145516Sdarrenr 157145516Sdarrenr /* Parse leading line options */ 158145516Sdarrenr strlcpy(options, "adklmnuv", sizeof(options)); 159145516Sdarrenr for (p = opts; p != NULL; p = p->next) 160145516Sdarrenr strlcat(options, p->opt, sizeof(options)); 161145516Sdarrenr while ((c = getopt(argc, argv, options)) != -1) { 162145516Sdarrenr switch (c) { 163145516Sdarrenr case 'a': /* scan all interfaces */ 164145516Sdarrenr all++; 165145516Sdarrenr break; 166145516Sdarrenr case 'd': /* restrict scan to "down" interfaces */ 167145516Sdarrenr downonly++; 168145516Sdarrenr break; 169145516Sdarrenr case 'k': 170145516Sdarrenr printkeys++; 171145516Sdarrenr break; 172145516Sdarrenr case 'l': /* scan interface names only */ 173145516Sdarrenr namesonly++; 174145516Sdarrenr break; 175145516Sdarrenr case 'm': /* show media choices in status */ 176145516Sdarrenr supmedia = 1; 177145516Sdarrenr break; 178145516Sdarrenr case 'n': /* suppress module loading */ 179145516Sdarrenr noload++; 180145516Sdarrenr break; 181145516Sdarrenr case 'u': /* restrict scan to "up" interfaces */ 182145516Sdarrenr uponly++; 183145516Sdarrenr break; 184145516Sdarrenr case 'v': 185145516Sdarrenr verbose++; 186145516Sdarrenr break; 187145516Sdarrenr default: 188145516Sdarrenr for (p = opts; p != NULL; p = p->next) 189145516Sdarrenr if (p->opt[0] == c) { 190145516Sdarrenr p->cb(optarg); 191145516Sdarrenr break; 192145516Sdarrenr } 193145516Sdarrenr if (p == NULL) 194145516Sdarrenr usage(); 195145516Sdarrenr break; 196145516Sdarrenr } 197145516Sdarrenr } 198145516Sdarrenr argc -= optind; 199145516Sdarrenr argv += optind; 200145516Sdarrenr 201145516Sdarrenr /* -l cannot be used with -a or -m */ 202145516Sdarrenr if (namesonly && (all || supmedia)) 203145516Sdarrenr usage(); 204145516Sdarrenr 205145516Sdarrenr /* nonsense.. */ 206145516Sdarrenr if (uponly && downonly) 207145516Sdarrenr usage(); 208145516Sdarrenr 209145516Sdarrenr /* no arguments is equivalent to '-a' */ 210145516Sdarrenr if (!namesonly && argc < 1) 211145516Sdarrenr all = 1; 212145516Sdarrenr 213145516Sdarrenr /* -a and -l allow an address family arg to limit the output */ 214145516Sdarrenr if (all || namesonly) { 215145516Sdarrenr if (argc > 1) 216145516Sdarrenr usage(); 217145516Sdarrenr 218145516Sdarrenr ifname = NULL; 219145516Sdarrenr ifindex = 0; 220145516Sdarrenr if (argc == 1) { 221145516Sdarrenr afp = af_getbyname(*argv); 222145516Sdarrenr if (afp == NULL) 223145516Sdarrenr usage(); 224145516Sdarrenr if (afp->af_name != NULL) 225145516Sdarrenr argc--, argv++; 226145516Sdarrenr /* leave with afp non-zero */ 227145516Sdarrenr } 228145516Sdarrenr } else { 229145516Sdarrenr /* not listing, need an argument */ 230145516Sdarrenr if (argc < 1) 231145516Sdarrenr usage(); 232145516Sdarrenr 233145516Sdarrenr ifname = *argv; 234145516Sdarrenr argc--, argv++; 235145516Sdarrenr 236145516Sdarrenr /* check and maybe load support for this interface */ 237145516Sdarrenr ifmaybeload(ifname); 238145516Sdarrenr 239145516Sdarrenr ifindex = if_nametoindex(ifname); 240145516Sdarrenr if (ifindex == 0) { 241145516Sdarrenr /* 242145516Sdarrenr * NOTE: We must special-case the `create' command 243145516Sdarrenr * right here as we would otherwise fail when trying 244145516Sdarrenr * to find the interface. 245145516Sdarrenr */ 246145516Sdarrenr if (argc > 0 && (strcmp(argv[0], "create") == 0 || 247145516Sdarrenr strcmp(argv[0], "plumb") == 0)) { 248145516Sdarrenr iflen = strlcpy(name, ifname, sizeof(name)); 249145516Sdarrenr if (iflen >= sizeof(name)) 250145516Sdarrenr errx(1, "%s: cloning name too long", 251145516Sdarrenr ifname); 252145516Sdarrenr ifconfig(argc, argv, 1, NULL); 253145516Sdarrenr exit(0); 254145516Sdarrenr } 255145516Sdarrenr errx(1, "interface %s does not exist", ifname); 256145516Sdarrenr } 257145516Sdarrenr } 258145516Sdarrenr 259145516Sdarrenr /* Check for address family */ 260145516Sdarrenr if (argc > 0) { 261145516Sdarrenr afp = af_getbyname(*argv); 262145516Sdarrenr if (afp != NULL) 263145516Sdarrenr argc--, argv++; 264145516Sdarrenr } 265145516Sdarrenr 266145516Sdarrenr if (getifaddrs(&ifap) != 0) 267145516Sdarrenr err(EXIT_FAILURE, "getifaddrs"); 268145516Sdarrenr cp = NULL; 269145516Sdarrenr ifindex = 0; 270145516Sdarrenr for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 271145516Sdarrenr memset(&paifr, 0, sizeof(paifr)); 272145516Sdarrenr strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 273145516Sdarrenr if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 274145516Sdarrenr memcpy(&paifr.ifr_addr, ifa->ifa_addr, 275145516Sdarrenr ifa->ifa_addr->sa_len); 276145516Sdarrenr } 277145516Sdarrenr 278145516Sdarrenr if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) 279145516Sdarrenr continue; 280145516Sdarrenr if (ifa->ifa_addr->sa_family == AF_LINK) 281145516Sdarrenr sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 282145516Sdarrenr else 283145516Sdarrenr sdl = NULL; 284145516Sdarrenr if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0) 285145516Sdarrenr continue; 286145516Sdarrenr iflen = strlcpy(name, ifa->ifa_name, sizeof(name)); 287145516Sdarrenr if (iflen >= sizeof(name)) { 288145516Sdarrenr warnx("%s: interface name too long, skipping", 289145516Sdarrenr ifa->ifa_name); 290145516Sdarrenr continue; 291145516Sdarrenr } 292145516Sdarrenr cp = ifa->ifa_name; 293145516Sdarrenr 294145516Sdarrenr if (downonly && (ifa->ifa_flags & IFF_UP) != 0) 295145516Sdarrenr continue; 296145516Sdarrenr if (uponly && (ifa->ifa_flags & IFF_UP) == 0) 297145516Sdarrenr continue; 298145516Sdarrenr ifindex++; 299145516Sdarrenr /* 300145516Sdarrenr * Are we just listing the interfaces? 301145516Sdarrenr */ 302145516Sdarrenr if (namesonly) { 303145516Sdarrenr if (ifindex > 1) 304145516Sdarrenr printf(" "); 305145516Sdarrenr fputs(name, stdout); 306145516Sdarrenr continue; 307145516Sdarrenr } 308145516Sdarrenr 309145516Sdarrenr if (argc > 0) 310145516Sdarrenr ifconfig(argc, argv, 0, afp); 311145516Sdarrenr else 312145516Sdarrenr status(afp, sdl, ifa); 313145516Sdarrenr } 314145516Sdarrenr if (namesonly) 315145516Sdarrenr printf("\n"); 316145516Sdarrenr freeifaddrs(ifap); 317145516Sdarrenr 318145516Sdarrenr exit(0); 319145516Sdarrenr} 320145516Sdarrenr 321145516Sdarrenrstatic struct afswtch *afs = NULL; 322145516Sdarrenr 323145516Sdarrenrvoid 324145516Sdarrenraf_register(struct afswtch *p) 325145516Sdarrenr{ 326145516Sdarrenr p->af_next = afs; 327145516Sdarrenr afs = p; 328145516Sdarrenr} 329145516Sdarrenr 330145516Sdarrenrstatic struct afswtch * 331145516Sdarrenraf_getbyname(const char *name) 332145516Sdarrenr{ 333145516Sdarrenr struct afswtch *afp; 334145516Sdarrenr 335145516Sdarrenr for (afp = afs; afp != NULL; afp = afp->af_next) 336145516Sdarrenr if (strcmp(afp->af_name, name) == 0) 337145516Sdarrenr return afp; 338145516Sdarrenr return NULL; 339145516Sdarrenr} 340145516Sdarrenr 341145516Sdarrenrstatic struct afswtch * 342145516Sdarrenraf_getbyfamily(int af) 343145516Sdarrenr{ 344145516Sdarrenr struct afswtch *afp; 345145516Sdarrenr 346145516Sdarrenr for (afp = afs; afp != NULL; afp = afp->af_next) 347145516Sdarrenr if (afp->af_af == af) 348145516Sdarrenr return afp; 349145516Sdarrenr return NULL; 350145516Sdarrenr} 351145516Sdarrenr 352145516Sdarrenrstatic void 353145516Sdarrenraf_other_status(int s) 354145516Sdarrenr{ 355145516Sdarrenr struct afswtch *afp; 356145516Sdarrenr uint8_t afmask[howmany(AF_MAX, NBBY)]; 357145516Sdarrenr 358145516Sdarrenr memset(afmask, 0, sizeof(afmask)); 359145516Sdarrenr for (afp = afs; afp != NULL; afp = afp->af_next) { 360145516Sdarrenr if (afp->af_other_status == NULL) 361145516Sdarrenr continue; 362145516Sdarrenr if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 363145516Sdarrenr continue; 364145516Sdarrenr afp->af_other_status(s); 365145516Sdarrenr setbit(afmask, afp->af_af); 366145516Sdarrenr } 367145516Sdarrenr} 368145516Sdarrenr 369145516Sdarrenrstatic void 370145516Sdarrenraf_all_tunnel_status(int s) 371145516Sdarrenr{ 372145516Sdarrenr struct afswtch *afp; 373145516Sdarrenr uint8_t afmask[howmany(AF_MAX, NBBY)]; 374145516Sdarrenr 375145516Sdarrenr memset(afmask, 0, sizeof(afmask)); 376145516Sdarrenr for (afp = afs; afp != NULL; afp = afp->af_next) { 377145516Sdarrenr if (afp->af_status_tunnel == NULL) 378145516Sdarrenr continue; 379145516Sdarrenr if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 380145516Sdarrenr continue; 381145516Sdarrenr afp->af_status_tunnel(s); 382145516Sdarrenr setbit(afmask, afp->af_af); 383145516Sdarrenr } 384145516Sdarrenr} 385145516Sdarrenr 386145516Sdarrenrstatic struct cmd *cmds = NULL; 387145516Sdarrenr 388145516Sdarrenrvoid 389145516Sdarrenrcmd_register(struct cmd *p) 390145516Sdarrenr{ 391145516Sdarrenr p->c_next = cmds; 392145516Sdarrenr cmds = p; 393145516Sdarrenr} 394145516Sdarrenr 395145516Sdarrenrstatic const struct cmd * 396145516Sdarrenrcmd_lookup(const char *name) 397145516Sdarrenr{ 398145516Sdarrenr#define N(a) (sizeof(a)/sizeof(a[0])) 399145516Sdarrenr const struct cmd *p; 400145516Sdarrenr 401145516Sdarrenr for (p = cmds; p != NULL; p = p->c_next) 402145516Sdarrenr if (strcmp(name, p->c_name) == 0) 403145516Sdarrenr return p; 404145516Sdarrenr return NULL; 405145516Sdarrenr#undef N 406145516Sdarrenr} 407145516Sdarrenr 408145516Sdarrenrstruct callback { 409145516Sdarrenr callback_func *cb_func; 410145516Sdarrenr void *cb_arg; 411145516Sdarrenr struct callback *cb_next; 412145516Sdarrenr}; 413145516Sdarrenrstatic struct callback *callbacks = NULL; 414145516Sdarrenr 415145516Sdarrenrvoid 416145516Sdarrenrcallback_register(callback_func *func, void *arg) 417145516Sdarrenr{ 418145516Sdarrenr struct callback *cb; 419145516Sdarrenr 420145516Sdarrenr cb = malloc(sizeof(struct callback)); 421145516Sdarrenr if (cb == NULL) 422145516Sdarrenr errx(1, "unable to allocate memory for callback"); 423145516Sdarrenr cb->cb_func = func; 424145516Sdarrenr cb->cb_arg = arg; 425145516Sdarrenr cb->cb_next = callbacks; 426145516Sdarrenr callbacks = cb; 427145516Sdarrenr} 428145516Sdarrenr 429145516Sdarrenr/* specially-handled commands */ 430145516Sdarrenrstatic void setifaddr(const char *, int, int, const struct afswtch *); 431145516Sdarrenrstatic const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); 432145516Sdarrenr 433145516Sdarrenrstatic void setifdstaddr(const char *, int, int, const struct afswtch *); 434145516Sdarrenrstatic const struct cmd setifdstaddr_cmd = 435145516Sdarrenr DEF_CMD("ifdstaddr", 0, setifdstaddr); 436145516Sdarrenr 437145516Sdarrenrstatic int 438145516Sdarrenrifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp) 439145516Sdarrenr{ 440145516Sdarrenr const struct afswtch *nafp; 441145516Sdarrenr struct callback *cb; 442145516Sdarrenr int s; 443145516Sdarrenr 444145516Sdarrenr strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 445145516Sdarrenrtop: 446145516Sdarrenr if (afp == NULL) 447145516Sdarrenr afp = af_getbyname("inet"); 448145516Sdarrenr ifr.ifr_addr.sa_family = 449145516Sdarrenr afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? 450145516Sdarrenr AF_INET : afp->af_af; 451145516Sdarrenr 452145516Sdarrenr if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 453145516Sdarrenr err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); 454145516Sdarrenr 455145516Sdarrenr while (argc > 0) { 456145516Sdarrenr const struct cmd *p; 457145516Sdarrenr 458145516Sdarrenr p = cmd_lookup(*argv); 459145516Sdarrenr if (p == NULL) { 460145516Sdarrenr /* 461145516Sdarrenr * Not a recognized command, choose between setting 462145516Sdarrenr * the interface address and the dst address. 463145516Sdarrenr */ 464145516Sdarrenr p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); 465145516Sdarrenr } 466145516Sdarrenr if (p->c_u.c_func || p->c_u.c_func2) { 467145516Sdarrenr if (iscreate && !p->c_iscloneop) { 468145516Sdarrenr /* 469145516Sdarrenr * Push the clone create callback so the new 470145516Sdarrenr * device is created and can be used for any 471145516Sdarrenr * remaining arguments. 472145516Sdarrenr */ 473145516Sdarrenr cb = callbacks; 474145516Sdarrenr if (cb == NULL) 475145516Sdarrenr errx(1, "internal error, no callback"); 476145516Sdarrenr callbacks = cb->cb_next; 477145516Sdarrenr cb->cb_func(s, cb->cb_arg); 478145516Sdarrenr iscreate = 0; 479145516Sdarrenr /* 480145516Sdarrenr * Handle any address family spec that 481145516Sdarrenr * immediately follows and potentially 482145516Sdarrenr * recreate the socket. 483145516Sdarrenr */ 484145516Sdarrenr nafp = af_getbyname(*argv); 485145516Sdarrenr if (nafp != NULL) { 486145516Sdarrenr argc--, argv++; 487145516Sdarrenr if (nafp != afp) { 488145516Sdarrenr close(s); 489145516Sdarrenr afp = nafp; 490145516Sdarrenr goto top; 491145516Sdarrenr } 492145516Sdarrenr } 493145516Sdarrenr } 494145516Sdarrenr if (p->c_parameter == NEXTARG) { 495145516Sdarrenr if (argv[1] == NULL) 496145516Sdarrenr errx(1, "'%s' requires argument", 497145516Sdarrenr p->c_name); 498145516Sdarrenr p->c_u.c_func(argv[1], 0, s, afp); 499145516Sdarrenr argc--, argv++; 500145516Sdarrenr } else if (p->c_parameter == OPTARG) { 501145516Sdarrenr p->c_u.c_func(argv[1], 0, s, afp); 502145516Sdarrenr if (argv[1] != NULL) 503145516Sdarrenr argc--, argv++; 504145516Sdarrenr } else if (p->c_parameter == NEXTARG2) { 505145516Sdarrenr if (argc < 3) 506145516Sdarrenr errx(1, "'%s' requires 2 arguments", 507145516Sdarrenr p->c_name); 508145516Sdarrenr p->c_u.c_func2(argv[1], argv[2], s, afp); 509145516Sdarrenr argc -= 2, argv += 2; 510145516Sdarrenr } else 511145516Sdarrenr p->c_u.c_func(*argv, p->c_parameter, s, afp); 512145516Sdarrenr } 513145516Sdarrenr argc--, argv++; 514145516Sdarrenr } 515145516Sdarrenr 516145516Sdarrenr /* 517145516Sdarrenr * Do any post argument processing required by the address family. 518145516Sdarrenr */ 519145516Sdarrenr if (afp->af_postproc != NULL) 520145516Sdarrenr afp->af_postproc(s, afp); 521145516Sdarrenr /* 522145516Sdarrenr * Do deferred callbacks registered while processing 523145516Sdarrenr * command-line arguments. 524145516Sdarrenr */ 525145516Sdarrenr for (cb = callbacks; cb != NULL; cb = cb->cb_next) 526145516Sdarrenr cb->cb_func(s, cb->cb_arg); 527145516Sdarrenr /* 528 * Do deferred operations. 529 */ 530 if (clearaddr) { 531 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 532 warnx("interface %s cannot change %s addresses!", 533 name, afp->af_name); 534 clearaddr = 0; 535 } 536 } 537 if (clearaddr) { 538 int ret; 539 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 540 ret = ioctl(s, afp->af_difaddr, afp->af_ridreq); 541 if (ret < 0) { 542 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 543 /* means no previous address for interface */ 544 } else 545 Perror("ioctl (SIOCDIFADDR)"); 546 } 547 } 548 if (newaddr) { 549 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 550 warnx("interface %s cannot change %s addresses!", 551 name, afp->af_name); 552 newaddr = 0; 553 } 554 } 555 if (newaddr && (setaddr || setmask)) { 556 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 557 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 558 Perror("ioctl (SIOCAIFADDR)"); 559 } 560 561 close(s); 562 return(0); 563} 564 565/*ARGSUSED*/ 566static void 567setifaddr(const char *addr, int param, int s, const struct afswtch *afp) 568{ 569 if (afp->af_getaddr == NULL) 570 return; 571 /* 572 * Delay the ioctl to set the interface addr until flags are all set. 573 * The address interpretation may depend on the flags, 574 * and the flags may change when the address is set. 575 */ 576 setaddr++; 577 if (doalias == 0 && afp->af_af != AF_LINK) 578 clearaddr = 1; 579 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); 580} 581 582static void 583settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) 584{ 585 struct addrinfo *srcres, *dstres; 586 int ecode; 587 588 if (afp->af_settunnel == NULL) { 589 warn("address family %s does not support tunnel setup", 590 afp->af_name); 591 return; 592 } 593 594 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 595 errx(1, "error in parsing address string: %s", 596 gai_strerror(ecode)); 597 598 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 599 errx(1, "error in parsing address string: %s", 600 gai_strerror(ecode)); 601 602 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 603 errx(1, 604 "source and destination address families do not match"); 605 606 afp->af_settunnel(s, srcres, dstres); 607 608 freeaddrinfo(srcres); 609 freeaddrinfo(dstres); 610} 611 612/* ARGSUSED */ 613static void 614deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) 615{ 616 617 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 618 err(1, "SIOCDIFPHYADDR"); 619} 620 621static void 622setifnetmask(const char *addr, int dummy __unused, int s, 623 const struct afswtch *afp) 624{ 625 if (afp->af_getaddr != NULL) { 626 setmask++; 627 afp->af_getaddr(addr, MASK); 628 } 629} 630 631static void 632setifbroadaddr(const char *addr, int dummy __unused, int s, 633 const struct afswtch *afp) 634{ 635 if (afp->af_getaddr != NULL) 636 afp->af_getaddr(addr, DSTADDR); 637} 638 639static void 640setifipdst(const char *addr, int dummy __unused, int s, 641 const struct afswtch *afp) 642{ 643 const struct afswtch *inet; 644 645 inet = af_getbyname("inet"); 646 if (inet == NULL) 647 return; 648 inet->af_getaddr(addr, DSTADDR); 649 clearaddr = 0; 650 newaddr = 0; 651} 652 653static void 654notealias(const char *addr, int param, int s, const struct afswtch *afp) 655{ 656#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 657 if (setaddr && doalias == 0 && param < 0) 658 if (afp->af_addreq != NULL && afp->af_ridreq != NULL) 659 bcopy((caddr_t)rqtosa(af_addreq), 660 (caddr_t)rqtosa(af_ridreq), 661 rqtosa(af_addreq)->sa_len); 662 doalias = param; 663 if (param < 0) { 664 clearaddr = 1; 665 newaddr = 0; 666 } else 667 clearaddr = 0; 668#undef rqtosa 669} 670 671/*ARGSUSED*/ 672static void 673setifdstaddr(const char *addr, int param __unused, int s, 674 const struct afswtch *afp) 675{ 676 if (afp->af_getaddr != NULL) 677 afp->af_getaddr(addr, DSTADDR); 678} 679 680/* 681 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 682 * of the ifreq structure, which may confuse other parts of ifconfig. 683 * Make a private copy so we can avoid that. 684 */ 685static void 686setifflags(const char *vname, int value, int s, const struct afswtch *afp) 687{ 688 struct ifreq my_ifr; 689 int flags; 690 691 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 692 693 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 694 Perror("ioctl (SIOCGIFFLAGS)"); 695 exit(1); 696 } 697 strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name)); 698 flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16); 699 700 if (value < 0) { 701 value = -value; 702 flags &= ~value; 703 } else 704 flags |= value; 705 my_ifr.ifr_flags = flags & 0xffff; 706 my_ifr.ifr_flagshigh = flags >> 16; 707 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 708 Perror(vname); 709} 710 711void 712setifcap(const char *vname, int value, int s, const struct afswtch *afp) 713{ 714 int flags; 715 716 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 717 Perror("ioctl (SIOCGIFCAP)"); 718 exit(1); 719 } 720 flags = ifr.ifr_curcap; 721 if (value < 0) { 722 value = -value; 723 flags &= ~value; 724 } else 725 flags |= value; 726 flags &= ifr.ifr_reqcap; 727 ifr.ifr_reqcap = flags; 728 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 729 Perror(vname); 730} 731 732static void 733setifmetric(const char *val, int dummy __unused, int s, 734 const struct afswtch *afp) 735{ 736 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 737 ifr.ifr_metric = atoi(val); 738 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 739 warn("ioctl (set metric)"); 740} 741 742static void 743setifmtu(const char *val, int dummy __unused, int s, 744 const struct afswtch *afp) 745{ 746 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 747 ifr.ifr_mtu = atoi(val); 748 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 749 warn("ioctl (set mtu)"); 750} 751 752static void 753setifgrekey(const char *val, int dummy __unused, int s, 754 const struct afswtch *afp) 755{ 756 uint32_t grekey = atol(val); 757 758 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 759 ifr.ifr_data = (caddr_t)&grekey; 760 if (ioctl(s, GRESKEY, (caddr_t)&ifr) < 0) 761 warn("ioctl (set grekey)"); 762} 763 764static void 765setifname(const char *val, int dummy __unused, int s, 766 const struct afswtch *afp) 767{ 768 char *newname; 769 770 newname = strdup(val); 771 if (newname == NULL) { 772 warn("no memory to set ifname"); 773 return; 774 } 775 ifr.ifr_data = newname; 776 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { 777 warn("ioctl (set name)"); 778 free(newname); 779 return; 780 } 781 strlcpy(name, newname, sizeof(name)); 782 free(newname); 783} 784 785#define IFFBITS \ 786"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 787"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 788"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25NEEDSGIANT" 789 790#define IFCAPBITS \ 791"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ 792"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" 793 794/* 795 * Print the status of the interface. If an address family was 796 * specified, show only it; otherwise, show them all. 797 */ 798static void 799status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 800 struct ifaddrs *ifa) 801{ 802 struct ifaddrs *ift; 803 int allfamilies, s; 804 struct ifstat ifs; 805 806 if (afp == NULL) { 807 allfamilies = 1; 808 afp = af_getbyname("inet"); 809 } else 810 allfamilies = 0; 811 812 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 813 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 814 815 s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); 816 if (s < 0) 817 err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); 818 819 printf("%s: ", name); 820 printb("flags", ifa->ifa_flags, IFFBITS); 821 if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) 822 printf(" metric %d", ifr.ifr_metric); 823 if (ioctl(s, SIOCGIFMTU, &ifr) != -1) 824 printf(" mtu %d", ifr.ifr_mtu); 825 putchar('\n'); 826 827 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { 828 if (ifr.ifr_curcap != 0) { 829 printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 830 putchar('\n'); 831 } 832 if (supmedia && ifr.ifr_reqcap != 0) { 833 printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS); 834 putchar('\n'); 835 } 836 } 837 838 tunnel_status(s); 839 840 for (ift = ifa; ift != NULL; ift = ift->ifa_next) { 841 if (ift->ifa_addr == NULL) 842 continue; 843 if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) 844 continue; 845 if (allfamilies) { 846 const struct afswtch *p; 847 p = af_getbyfamily(ift->ifa_addr->sa_family); 848 if (p != NULL && p->af_status != NULL) 849 p->af_status(s, ift); 850 } else if (afp->af_af == ift->ifa_addr->sa_family) 851 afp->af_status(s, ift); 852 } 853#if 0 854 if (allfamilies || afp->af_af == AF_LINK) { 855 const struct afswtch *lafp; 856 857 /* 858 * Hack; the link level address is received separately 859 * from the routing information so any address is not 860 * handled above. Cobble together an entry and invoke 861 * the status method specially. 862 */ 863 lafp = af_getbyname("lladdr"); 864 if (lafp != NULL) { 865 info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl; 866 lafp->af_status(s, &info); 867 } 868 } 869#endif 870 if (allfamilies) 871 af_other_status(s); 872 else if (afp->af_other_status != NULL) 873 afp->af_other_status(s); 874 875 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 876 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 877 printf("%s", ifs.ascii); 878 879 int grekey = 0; 880 ifr.ifr_data = (caddr_t)&grekey; 881 if (ioctl(s, GREGKEY, &ifr) == 0) 882 if (grekey != 0) 883 printf("\tgrekey: %d\n", grekey); 884 885 close(s); 886 return; 887} 888 889static void 890tunnel_status(int s) 891{ 892 af_all_tunnel_status(s); 893} 894 895void 896Perror(const char *cmd) 897{ 898 switch (errno) { 899 900 case ENXIO: 901 errx(1, "%s: no such interface", cmd); 902 break; 903 904 case EPERM: 905 errx(1, "%s: permission denied", cmd); 906 break; 907 908 default: 909 err(1, "%s", cmd); 910 } 911} 912 913/* 914 * Print a value a la the %b format of the kernel's printf 915 */ 916void 917printb(const char *s, unsigned v, const char *bits) 918{ 919 int i, any = 0; 920 char c; 921 922 if (bits && *bits == 8) 923 printf("%s=%o", s, v); 924 else 925 printf("%s=%x", s, v); 926 bits++; 927 if (bits) { 928 putchar('<'); 929 while ((i = *bits++) != '\0') { 930 if (v & (1 << (i-1))) { 931 if (any) 932 putchar(','); 933 any = 1; 934 for (; (c = *bits) > 32; bits++) 935 putchar(c); 936 } else 937 for (; *bits > 32; bits++) 938 ; 939 } 940 putchar('>'); 941 } 942} 943 944void 945ifmaybeload(const char *name) 946{ 947#define MOD_PREFIX_LEN 3 /* "if_" */ 948 struct module_stat mstat; 949 int fileid, modid; 950 char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; 951 const char *cp; 952 953 /* loading suppressed by the user */ 954 if (noload) 955 return; 956 957 /* trim the interface number off the end */ 958 strlcpy(ifname, name, sizeof(ifname)); 959 for (dp = ifname; *dp != 0; dp++) 960 if (isdigit(*dp)) { 961 *dp = 0; 962 break; 963 } 964 965 /* turn interface and unit into module name */ 966 strcpy(ifkind, "if_"); 967 strlcpy(ifkind + MOD_PREFIX_LEN, ifname, 968 sizeof(ifkind) - MOD_PREFIX_LEN); 969 970 /* scan files in kernel */ 971 mstat.version = sizeof(struct module_stat); 972 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 973 /* scan modules in file */ 974 for (modid = kldfirstmod(fileid); modid > 0; 975 modid = modfnext(modid)) { 976 if (modstat(modid, &mstat) < 0) 977 continue; 978 /* strip bus name if present */ 979 if ((cp = strchr(mstat.name, '/')) != NULL) { 980 cp++; 981 } else { 982 cp = mstat.name; 983 } 984 /* already loaded? */ 985 if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 || 986 strncmp(ifkind, cp, strlen(ifkind) + 1) == 0) 987 return; 988 } 989 } 990 991 /* not present, we should try to load it */ 992 kldload(ifkind); 993} 994 995static struct cmd basic_cmds[] = { 996 DEF_CMD("up", IFF_UP, setifflags), 997 DEF_CMD("down", -IFF_UP, setifflags), 998 DEF_CMD("arp", -IFF_NOARP, setifflags), 999 DEF_CMD("-arp", IFF_NOARP, setifflags), 1000 DEF_CMD("debug", IFF_DEBUG, setifflags), 1001 DEF_CMD("-debug", -IFF_DEBUG, setifflags), 1002 DEF_CMD("promisc", IFF_PPROMISC, setifflags), 1003 DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), 1004 DEF_CMD("add", IFF_UP, notealias), 1005 DEF_CMD("alias", IFF_UP, notealias), 1006 DEF_CMD("-alias", -IFF_UP, notealias), 1007 DEF_CMD("delete", -IFF_UP, notealias), 1008 DEF_CMD("remove", -IFF_UP, notealias), 1009#ifdef notdef 1010#define EN_SWABIPS 0x1000 1011 DEF_CMD("swabips", EN_SWABIPS, setifflags), 1012 DEF_CMD("-swabips", -EN_SWABIPS, setifflags), 1013#endif 1014 DEF_CMD_ARG("netmask", setifnetmask), 1015 DEF_CMD_ARG("metric", setifmetric), 1016 DEF_CMD_ARG("broadcast", setifbroadaddr), 1017 DEF_CMD_ARG("ipdst", setifipdst), 1018 DEF_CMD_ARG2("tunnel", settunnel), 1019 DEF_CMD("-tunnel", 0, deletetunnel), 1020 DEF_CMD("deletetunnel", 0, deletetunnel), 1021 DEF_CMD("link0", IFF_LINK0, setifflags), 1022 DEF_CMD("-link0", -IFF_LINK0, setifflags), 1023 DEF_CMD("link1", IFF_LINK1, setifflags), 1024 DEF_CMD("-link1", -IFF_LINK1, setifflags), 1025 DEF_CMD("link2", IFF_LINK2, setifflags), 1026 DEF_CMD("-link2", -IFF_LINK2, setifflags), 1027 DEF_CMD("monitor", IFF_MONITOR, setifflags), 1028 DEF_CMD("-monitor", -IFF_MONITOR, setifflags), 1029 DEF_CMD("staticarp", IFF_STATICARP, setifflags), 1030 DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), 1031 DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), 1032 DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), 1033 DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), 1034 DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), 1035 DEF_CMD("netcons", IFCAP_NETCONS, setifcap), 1036 DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), 1037 DEF_CMD("polling", IFCAP_POLLING, setifcap), 1038 DEF_CMD("-polling", -IFCAP_POLLING, setifcap), 1039 DEF_CMD("tso", IFCAP_TSO, setifcap), 1040 DEF_CMD("-tso", -IFCAP_TSO, setifcap), 1041 DEF_CMD("lro", IFCAP_LRO, setifcap), 1042 DEF_CMD("-lro", -IFCAP_LRO, setifcap), 1043 DEF_CMD("wol", IFCAP_WOL, setifcap), 1044 DEF_CMD("-wol", -IFCAP_WOL, setifcap), 1045 DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), 1046 DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), 1047 DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), 1048 DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), 1049 DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), 1050 DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), 1051 DEF_CMD("normal", -IFF_LINK0, setifflags), 1052 DEF_CMD("compress", IFF_LINK0, setifflags), 1053 DEF_CMD("noicmp", IFF_LINK1, setifflags), 1054 DEF_CMD_ARG("mtu", setifmtu), 1055 DEF_CMD_ARG("name", setifname), 1056 DEF_CMD_ARG("grekey", setifgrekey), 1057}; 1058 1059static __constructor void 1060ifconfig_ctor(void) 1061{ 1062#define N(a) (sizeof(a) / sizeof(a[0])) 1063 int i; 1064 1065 for (i = 0; i < N(basic_cmds); i++) 1066 cmd_register(&basic_cmds[i]); 1067#undef N 1068} 1069