ifconfig.c revision 191252
1133819Stjr/* 2133819Stjr * Copyright (c) 1983, 1993 3133819Stjr * The Regents of the University of California. All rights reserved. 4133819Stjr * 5133819Stjr * Redistribution and use in source and binary forms, with or without 6177258Srdivacky * modification, are permitted provided that the following conditions 7133819Stjr * are met: 8133819Stjr * 1. Redistributions of source code must retain the above copyright 9133819Stjr * notice, this list of conditions and the following disclaimer. 10133819Stjr * 2. Redistributions in binary form must reproduce the above copyright 11133819Stjr * notice, this list of conditions and the following disclaimer in the 12133819Stjr * documentation and/or other materials provided with the distribution. 13133819Stjr * 4. Neither the name of the University nor the names of its contributors 14164199Sru * may be used to endorse or promote products derived from this software 15133819Stjr * without specific prior written permission. 16133819Stjr * 17161330Sjhb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18161330Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19133819Stjr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20133819Stjr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21133819Stjr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22133819Stjr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23133819Stjr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24133819Stjr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25133819Stjr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26133819Stjr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27133819Stjr * SUCH DAMAGE. 28133819Stjr */ 29133819Stjr 30133819Stjr#ifndef lint 31133819Stjrstatic const char copyright[] = 32133819Stjr"@(#) Copyright (c) 1983, 1993\n\ 33133819Stjr The Regents of the University of California. All rights reserved.\n"; 34143198Ssobomax#endif /* not lint */ 35133819Stjr 36133819Stjr#ifndef lint 37133819Stjr#if 0 38133819Stjrstatic char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 39133819Stjr#endif 40133819Stjrstatic const char rcsid[] = 41133819Stjr "$FreeBSD: head/sbin/ifconfig/ifconfig.c 191252 2009-04-18 20:10:39Z rwatson $"; 42133819Stjr#endif /* not lint */ 43133819Stjr 44133819Stjr#include <sys/param.h> 45133819Stjr#include <sys/ioctl.h> 46133819Stjr#include <sys/socket.h> 47133819Stjr#include <sys/sysctl.h> 48133819Stjr#include <sys/time.h> 49133819Stjr#include <sys/module.h> 50133819Stjr#include <sys/linker.h> 51133819Stjr 52133819Stjr#include <net/ethernet.h> 53133819Stjr#include <net/if.h> 54133819Stjr#include <net/if_var.h> 55133819Stjr#include <net/if_dl.h> 56133819Stjr#include <net/if_types.h> 57133819Stjr#include <net/route.h> 58133819Stjr 59133819Stjr/* IP */ 60133819Stjr#include <netinet/in.h> 61133819Stjr#include <netinet/in_var.h> 62133819Stjr#include <arpa/inet.h> 63133819Stjr#include <netdb.h> 64133819Stjr 65133819Stjr#include <ifaddrs.h> 66133819Stjr#include <ctype.h> 67133819Stjr#include <err.h> 68133819Stjr#include <errno.h> 69133819Stjr#include <fcntl.h> 70133819Stjr#include <stdio.h> 71133819Stjr#include <stdlib.h> 72133819Stjr#include <string.h> 73133819Stjr#include <unistd.h> 74133819Stjr 75133819Stjr#include "ifconfig.h" 76133819Stjr 77133819Stjr/* 78133819Stjr * Since "struct ifreq" is composed of various union members, callers 79133819Stjr * should pay special attention to interprete the value. 80133819Stjr * (.e.g. little/big endian difference in the structure.) 81133819Stjr */ 82133819Stjrstruct ifreq ifr; 83133819Stjr 84156919Snetchildchar name[IFNAMSIZ]; 85156919Snetchildint setaddr; 86156919Snetchildint setmask; 87156919Snetchildint doalias; 88133819Stjrint clearaddr; 89133819Stjrint newaddr = 1; 90133819Stjrint verbose; 91133819Stjrint noload; 92133819Stjr 93133819Stjrint supmedia = 0; 94133819Stjrint printkeys = 0; /* Print keying material for interfaces. */ 95133819Stjr 96133819Stjrstatic int ifconfig(int argc, char *const *argv, int iscreate, 97133819Stjr const struct afswtch *afp); 98133819Stjrstatic void status(const struct afswtch *afp, const struct sockaddr_dl *sdl, 99133819Stjr struct ifaddrs *ifa); 100133819Stjrstatic void tunnel_status(int s); 101133819Stjrstatic void usage(void); 102133819Stjr 103133819Stjrstatic struct afswtch *af_getbyname(const char *name); 104133819Stjrstatic struct afswtch *af_getbyfamily(int af); 105133819Stjrstatic void af_other_status(int); 106133819Stjr 107133819Stjrstatic struct option *opts = NULL; 108133819Stjr 109133819Stjrvoid 110133819Stjropt_register(struct option *p) 111133819Stjr{ 112133819Stjr p->next = opts; 113133819Stjr opts = p; 114133819Stjr} 115133819Stjr 116133819Stjrstatic void 117133819Stjrusage(void) 118133819Stjr{ 119133819Stjr char options[1024]; 120133819Stjr struct option *p; 121133819Stjr 122133819Stjr /* XXX not right but close enough for now */ 123133819Stjr options[0] = '\0'; 124133819Stjr for (p = opts; p != NULL; p = p->next) { 125133819Stjr strlcat(options, p->opt_usage, sizeof(options)); 126133819Stjr strlcat(options, " ", sizeof(options)); 127133819Stjr } 128133819Stjr 129133819Stjr fprintf(stderr, 130133819Stjr "usage: ifconfig %sinterface address_family [address [dest_address]]\n" 131133819Stjr " [parameters]\n" 132133819Stjr " ifconfig interface create\n" 133133819Stjr " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n" 134133819Stjr " ifconfig -l [-d] [-u] [address_family]\n" 135133819Stjr " ifconfig %s[-d] [-m] [-u] [-v]\n", 136133819Stjr options, options, options); 137133819Stjr exit(1); 138133819Stjr} 139133819Stjr 140133819Stjrint 141133819Stjrmain(int argc, char *argv[]) 142133819Stjr{ 143133819Stjr int c, all, namesonly, downonly, uponly; 144133819Stjr const struct afswtch *afp = NULL; 145133819Stjr int ifindex; 146133819Stjr struct ifaddrs *ifap, *ifa; 147133819Stjr struct ifreq paifr; 148133819Stjr const struct sockaddr_dl *sdl; 149133819Stjr char options[1024], *cp; 150133819Stjr const char *ifname; 151133819Stjr struct option *p; 152133819Stjr size_t iflen; 153133819Stjr 154133819Stjr all = downonly = uponly = namesonly = noload = verbose = 0; 155133819Stjr 156133819Stjr /* Parse leading line options */ 157133819Stjr strlcpy(options, "adklmnuv", sizeof(options)); 158133819Stjr for (p = opts; p != NULL; p = p->next) 159133819Stjr strlcat(options, p->opt, sizeof(options)); 160133819Stjr while ((c = getopt(argc, argv, options)) != -1) { 161133819Stjr switch (c) { 162133819Stjr case 'a': /* scan all interfaces */ 163133819Stjr all++; 164133819Stjr break; 165133819Stjr case 'd': /* restrict scan to "down" interfaces */ 166133819Stjr downonly++; 167133819Stjr break; 168133819Stjr case 'k': 169133819Stjr printkeys++; 170133819Stjr break; 171133819Stjr case 'l': /* scan interface names only */ 172133819Stjr namesonly++; 173133819Stjr break; 174133819Stjr case 'm': /* show media choices in status */ 175133819Stjr supmedia = 1; 176133819Stjr break; 177133819Stjr case 'n': /* suppress module loading */ 178133819Stjr noload++; 179133819Stjr break; 180133819Stjr case 'u': /* restrict scan to "up" interfaces */ 181133819Stjr uponly++; 182133819Stjr break; 183133819Stjr case 'v': 184133819Stjr verbose++; 185133819Stjr break; 186133819Stjr default: 187133819Stjr for (p = opts; p != NULL; p = p->next) 188133819Stjr if (p->opt[0] == c) { 189133819Stjr p->cb(optarg); 190133819Stjr break; 191133819Stjr } 192133819Stjr if (p == NULL) 193133819Stjr usage(); 194133819Stjr break; 195133819Stjr } 196133819Stjr } 197133819Stjr argc -= optind; 198133819Stjr argv += optind; 199161309Snetchild 200161309Snetchild /* -l cannot be used with -a or -m */ 201161309Snetchild if (namesonly && (all || supmedia)) 202133819Stjr usage(); 203133819Stjr 204133819Stjr /* nonsense.. */ 205133819Stjr if (uponly && downonly) 206133819Stjr usage(); 207133819Stjr 208133819Stjr /* no arguments is equivalent to '-a' */ 209133819Stjr if (!namesonly && argc < 1) 210133819Stjr all = 1; 211133819Stjr 212133819Stjr /* -a and -l allow an address family arg to limit the output */ 213133819Stjr if (all || namesonly) { 214133819Stjr if (argc > 1) 215133819Stjr usage(); 216133819Stjr 217133819Stjr ifname = NULL; 218133819Stjr ifindex = 0; 219133819Stjr if (argc == 1) { 220133819Stjr afp = af_getbyname(*argv); 221133819Stjr if (afp == NULL) 222133819Stjr usage(); 223133819Stjr if (afp->af_name != NULL) 224133819Stjr argc--, argv++; 225133819Stjr /* leave with afp non-zero */ 226133819Stjr } 227133819Stjr } else { 228133819Stjr /* not listing, need an argument */ 229156843Snetchild if (argc < 1) 230156843Snetchild usage(); 231156843Snetchild 232156843Snetchild ifname = *argv; 233133819Stjr argc--, argv++; 234133819Stjr 235133819Stjr /* check and maybe load support for this interface */ 236133819Stjr ifmaybeload(ifname); 237133819Stjr 238133819Stjr ifindex = if_nametoindex(ifname); 239133819Stjr if (ifindex == 0) { 240133819Stjr /* 241133819Stjr * NOTE: We must special-case the `create' command 242133819Stjr * right here as we would otherwise fail when trying 243133819Stjr * to find the interface. 244133819Stjr */ 245133819Stjr if (argc > 0 && (strcmp(argv[0], "create") == 0 || 246133819Stjr strcmp(argv[0], "plumb") == 0)) { 247133819Stjr iflen = strlcpy(name, ifname, sizeof(name)); 248133819Stjr if (iflen >= sizeof(name)) 249133819Stjr errx(1, "%s: cloning name too long", 250133819Stjr ifname); 251133819Stjr ifconfig(argc, argv, 1, NULL); 252133819Stjr exit(0); 253133819Stjr } 254133819Stjr errx(1, "interface %s does not exist", ifname); 255133819Stjr } 256133819Stjr } 257133819Stjr 258133819Stjr /* Check for address family */ 259133819Stjr if (argc > 0) { 260133819Stjr afp = af_getbyname(*argv); 261133819Stjr if (afp != NULL) 262133819Stjr argc--, argv++; 263133819Stjr } 264133819Stjr 265133819Stjr if (getifaddrs(&ifap) != 0) 266133819Stjr err(EXIT_FAILURE, "getifaddrs"); 267133819Stjr cp = NULL; 268156919Snetchild ifindex = 0; 269156843Snetchild for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 270156919Snetchild memset(&paifr, 0, sizeof(paifr)); 271156843Snetchild strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 272133819Stjr if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 273133819Stjr memcpy(&paifr.ifr_addr, ifa->ifa_addr, 274133819Stjr ifa->ifa_addr->sa_len); 275133819Stjr } 276133819Stjr 277133819Stjr if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) 278133819Stjr continue; 279133819Stjr if (ifa->ifa_addr->sa_family == AF_LINK) 280133819Stjr sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 281133819Stjr else 282133819Stjr sdl = NULL; 283133819Stjr if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0) 284133819Stjr continue; 285133819Stjr iflen = strlcpy(name, ifa->ifa_name, sizeof(name)); 286133819Stjr if (iflen >= sizeof(name)) { 287133819Stjr warnx("%s: interface name too long, skipping", 288133819Stjr ifa->ifa_name); 289133819Stjr continue; 290133819Stjr } 291133819Stjr cp = ifa->ifa_name; 292133819Stjr 293133819Stjr if (downonly && (ifa->ifa_flags & IFF_UP) != 0) 294133819Stjr continue; 295156843Snetchild if (uponly && (ifa->ifa_flags & IFF_UP) == 0) 296156843Snetchild continue; 297156843Snetchild ifindex++; 298156843Snetchild /* 299147142Ssobomax * Are we just listing the interfaces? 300147142Ssobomax */ 301147142Ssobomax if (namesonly) { 302147142Ssobomax if (ifindex > 1) 303133819Stjr printf(" "); 304133819Stjr fputs(name, stdout); 305133819Stjr continue; 306133819Stjr } 307133819Stjr 308133819Stjr if (argc > 0) 309133819Stjr ifconfig(argc, argv, 0, afp); 310133819Stjr else 311133819Stjr status(afp, sdl, ifa); 312133819Stjr } 313133819Stjr if (namesonly) 314133819Stjr printf("\n"); 315133819Stjr freeifaddrs(ifap); 316133819Stjr 317133819Stjr exit(0); 318133819Stjr} 319133819Stjr 320133819Stjrstatic struct afswtch *afs = NULL; 321133819Stjr 322133819Stjrvoid 323133819Stjraf_register(struct afswtch *p) 324133819Stjr{ 325133819Stjr p->af_next = afs; 326133819Stjr afs = p; 327133819Stjr} 328133819Stjr 329133819Stjrstatic struct afswtch * 330133819Stjraf_getbyname(const char *name) 331133819Stjr{ 332133819Stjr struct afswtch *afp; 333133819Stjr 334133819Stjr for (afp = afs; afp != NULL; afp = afp->af_next) 335133819Stjr if (strcmp(afp->af_name, name) == 0) 336133819Stjr return afp; 337133819Stjr return NULL; 338133819Stjr} 339133819Stjr 340133819Stjrstatic struct afswtch * 341133819Stjraf_getbyfamily(int af) 342133819Stjr{ 343133819Stjr struct afswtch *afp; 344166730Sjkim 345166730Sjkim for (afp = afs; afp != NULL; afp = afp->af_next) 346166730Sjkim if (afp->af_af == af) 347133819Stjr return afp; 348133819Stjr return NULL; 349133819Stjr} 350133819Stjr 351133819Stjrstatic void 352133819Stjraf_other_status(int s) 353133819Stjr{ 354133819Stjr struct afswtch *afp; 355133819Stjr uint8_t afmask[howmany(AF_MAX, NBBY)]; 356133819Stjr 357133819Stjr memset(afmask, 0, sizeof(afmask)); 358133819Stjr for (afp = afs; afp != NULL; afp = afp->af_next) { 359133819Stjr if (afp->af_other_status == NULL) 360133819Stjr continue; 361133819Stjr if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 362133819Stjr continue; 363133819Stjr afp->af_other_status(s); 364133819Stjr setbit(afmask, afp->af_af); 365133819Stjr } 366133819Stjr} 367133819Stjr 368133819Stjrstatic void 369133819Stjraf_all_tunnel_status(int s) 370133819Stjr{ 371133819Stjr struct afswtch *afp; 372133819Stjr uint8_t afmask[howmany(AF_MAX, NBBY)]; 373133819Stjr 374133819Stjr memset(afmask, 0, sizeof(afmask)); 375133819Stjr for (afp = afs; afp != NULL; afp = afp->af_next) { 376161309Snetchild if (afp->af_status_tunnel == NULL) 377161309Snetchild continue; 378161309Snetchild if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af)) 379133819Stjr continue; 380133819Stjr afp->af_status_tunnel(s); 381133819Stjr setbit(afmask, afp->af_af); 382133819Stjr } 383133819Stjr} 384133819Stjr 385133819Stjrstatic struct cmd *cmds = NULL; 386133819Stjr 387133819Stjrvoid 388133819Stjrcmd_register(struct cmd *p) 389133819Stjr{ 390133819Stjr p->c_next = cmds; 391133819Stjr cmds = p; 392133819Stjr} 393133819Stjr 394133819Stjrstatic const struct cmd * 395133819Stjrcmd_lookup(const char *name, int iscreate) 396133819Stjr{ 397133819Stjr#define N(a) (sizeof(a)/sizeof(a[0])) 398133819Stjr const struct cmd *p; 399133819Stjr 400133819Stjr for (p = cmds; p != NULL; p = p->c_next) 401133819Stjr if (strcmp(name, p->c_name) == 0) { 402133819Stjr if (iscreate) { 403133819Stjr if (p->c_iscloneop) 404133819Stjr return p; 405133819Stjr } else { 406133819Stjr if (!p->c_iscloneop) 407133819Stjr return p; 408133819Stjr } 409133819Stjr } 410133819Stjr return NULL; 411133819Stjr#undef N 412133819Stjr} 413133819Stjr 414133819Stjrstruct callback { 415133819Stjr callback_func *cb_func; 416133819Stjr void *cb_arg; 417133819Stjr struct callback *cb_next; 418133819Stjr}; 419133819Stjrstatic struct callback *callbacks = NULL; 420133819Stjr 421133819Stjrvoid 422133819Stjrcallback_register(callback_func *func, void *arg) 423133819Stjr{ 424133819Stjr struct callback *cb; 425133819Stjr 426133819Stjr cb = malloc(sizeof(struct callback)); 427133819Stjr if (cb == NULL) 428133819Stjr errx(1, "unable to allocate memory for callback"); 429133819Stjr cb->cb_func = func; 430133819Stjr cb->cb_arg = arg; 431133819Stjr cb->cb_next = callbacks; 432133819Stjr callbacks = cb; 433133819Stjr} 434133819Stjr 435133819Stjr/* specially-handled commands */ 436133819Stjrstatic void setifaddr(const char *, int, int, const struct afswtch *); 437133819Stjrstatic const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr); 438133819Stjr 439133819Stjrstatic void setifdstaddr(const char *, int, int, const struct afswtch *); 440133819Stjrstatic const struct cmd setifdstaddr_cmd = 441133819Stjr DEF_CMD("ifdstaddr", 0, setifdstaddr); 442133819Stjr 443133819Stjrstatic int 444133819Stjrifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp) 445133819Stjr{ 446133819Stjr const struct afswtch *afp, *nafp; 447133819Stjr const struct cmd *p; 448133819Stjr struct callback *cb; 449133819Stjr int s; 450133819Stjr 451133819Stjr strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 452133819Stjr afp = uafp != NULL ? uafp : af_getbyname("inet"); 453133819Stjrtop: 454133819Stjr ifr.ifr_addr.sa_family = 455133819Stjr afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ? 456133819Stjr AF_LOCAL : afp->af_af; 457133819Stjr 458133819Stjr if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 && 459133819Stjr (uafp != NULL || errno != EPROTONOSUPPORT || 460133819Stjr (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) 461133819Stjr err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); 462133819Stjr 463133819Stjr while (argc > 0) { 464133819Stjr p = cmd_lookup(*argv, iscreate); 465133819Stjr if (iscreate && p == NULL) { 466133819Stjr /* 467133819Stjr * Push the clone create callback so the new 468133819Stjr * device is created and can be used for any 469133819Stjr * remaining arguments. 470133819Stjr */ 471133819Stjr cb = callbacks; 472133819Stjr if (cb == NULL) 473133819Stjr errx(1, "internal error, no callback"); 474133819Stjr callbacks = cb->cb_next; 475133819Stjr cb->cb_func(s, cb->cb_arg); 476133819Stjr iscreate = 0; 477133819Stjr /* 478133819Stjr * Handle any address family spec that 479133819Stjr * immediately follows and potentially 480133819Stjr * recreate the socket. 481133819Stjr */ 482133819Stjr nafp = af_getbyname(*argv); 483133819Stjr if (nafp != NULL) { 484133819Stjr argc--, argv++; 485133819Stjr if (nafp != afp) { 486133819Stjr close(s); 487133819Stjr afp = nafp; 488133819Stjr goto top; 489133819Stjr } 490133819Stjr } 491133819Stjr /* 492133819Stjr * Look for a normal parameter. 493133819Stjr */ 494133819Stjr continue; 495133819Stjr } 496133819Stjr if (p == NULL) { 497133819Stjr /* 498133819Stjr * Not a recognized command, choose between setting 499133819Stjr * the interface address and the dst address. 500133819Stjr */ 501133819Stjr p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd); 502133819Stjr } 503133819Stjr if (p->c_u.c_func || p->c_u.c_func2) { 504133819Stjr if (p->c_parameter == NEXTARG) { 505133819Stjr if (argv[1] == NULL) 506133819Stjr errx(1, "'%s' requires argument", 507133819Stjr p->c_name); 508133819Stjr p->c_u.c_func(argv[1], 0, s, afp); 509133819Stjr argc--, argv++; 510133819Stjr } else if (p->c_parameter == OPTARG) { 511133819Stjr p->c_u.c_func(argv[1], 0, s, afp); 512133819Stjr if (argv[1] != NULL) 513133819Stjr argc--, argv++; 514133819Stjr } else if (p->c_parameter == NEXTARG2) { 515133819Stjr if (argc < 3) 516133819Stjr errx(1, "'%s' requires 2 arguments", 517133819Stjr p->c_name); 518133819Stjr p->c_u.c_func2(argv[1], argv[2], s, afp); 519133819Stjr argc -= 2, argv += 2; 520133819Stjr } else 521133819Stjr p->c_u.c_func(*argv, p->c_parameter, s, afp); 522133819Stjr } 523133819Stjr argc--, argv++; 524133819Stjr } 525133819Stjr 526133819Stjr /* 527163736Snetchild * Do any post argument processing required by the address family. 528163736Snetchild */ 529163736Snetchild if (afp->af_postproc != NULL) 530163736Snetchild afp->af_postproc(s, afp); 531163736Snetchild /* 532133819Stjr * Do deferred callbacks registered while processing 533133819Stjr * command-line arguments. 534133819Stjr */ 535133819Stjr for (cb = callbacks; cb != NULL; cb = cb->cb_next) 536133819Stjr cb->cb_func(s, cb->cb_arg); 537133819Stjr /* 538133819Stjr * Do deferred operations. 539133819Stjr */ 540133819Stjr if (clearaddr) { 541133819Stjr if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 542133819Stjr warnx("interface %s cannot change %s addresses!", 543133819Stjr name, afp->af_name); 544133819Stjr clearaddr = 0; 545133819Stjr } 546133819Stjr } 547133819Stjr if (clearaddr) { 548133819Stjr int ret; 549158407Snetchild strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 550158407Snetchild ret = ioctl(s, afp->af_difaddr, afp->af_ridreq); 551133819Stjr if (ret < 0) { 552133819Stjr if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 553165690Snetchild /* means no previous address for interface */ 554165690Snetchild } else 555165690Snetchild Perror("ioctl (SIOCDIFADDR)"); 556165690Snetchild } 557133819Stjr } 558133819Stjr if (newaddr) { 559133819Stjr if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 560133819Stjr warnx("interface %s cannot change %s addresses!", 561133819Stjr name, afp->af_name); 562133819Stjr newaddr = 0; 563133819Stjr } 564133819Stjr } 565133819Stjr if (newaddr && (setaddr || setmask)) { 566133819Stjr strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 567133819Stjr if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 568133819Stjr Perror("ioctl (SIOCAIFADDR)"); 569133819Stjr } 570133819Stjr 571133819Stjr close(s); 572133819Stjr return(0); 573133819Stjr} 574133819Stjr 575133819Stjr/*ARGSUSED*/ 576133819Stjrstatic void 577133819Stjrsetifaddr(const char *addr, int param, int s, const struct afswtch *afp) 578133819Stjr{ 579133819Stjr if (afp->af_getaddr == NULL) 580133819Stjr return; 581133819Stjr /* 582133819Stjr * Delay the ioctl to set the interface addr until flags are all set. 583133819Stjr * The address interpretation may depend on the flags, 584133819Stjr * and the flags may change when the address is set. 585133819Stjr */ 586133819Stjr setaddr++; 587133819Stjr if (doalias == 0 && afp->af_af != AF_LINK) 588133819Stjr clearaddr = 1; 589133819Stjr afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); 590133819Stjr} 591133819Stjr 592133819Stjrstatic void 593133819Stjrsettunnel(const char *src, const char *dst, int s, const struct afswtch *afp) 594133819Stjr{ 595133819Stjr struct addrinfo *srcres, *dstres; 596133819Stjr int ecode; 597133819Stjr 598133819Stjr if (afp->af_settunnel == NULL) { 599133819Stjr warn("address family %s does not support tunnel setup", 600133819Stjr afp->af_name); 601133819Stjr return; 602133819Stjr } 603133819Stjr 604133819Stjr if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 605133819Stjr errx(1, "error in parsing address string: %s", 606133819Stjr gai_strerror(ecode)); 607133819Stjr 608133819Stjr if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 609133819Stjr errx(1, "error in parsing address string: %s", 610133819Stjr gai_strerror(ecode)); 611133819Stjr 612133819Stjr if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 613133819Stjr errx(1, 614133819Stjr "source and destination address families do not match"); 615133819Stjr 616133819Stjr afp->af_settunnel(s, srcres, dstres); 617133819Stjr 618133819Stjr freeaddrinfo(srcres); 619133819Stjr freeaddrinfo(dstres); 620133819Stjr} 621133819Stjr 622133819Stjr/* ARGSUSED */ 623133819Stjrstatic void 624133819Stjrdeletetunnel(const char *vname, int param, int s, const struct afswtch *afp) 625133819Stjr{ 626133819Stjr 627133819Stjr if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 628133819Stjr err(1, "SIOCDIFPHYADDR"); 629133819Stjr} 630133819Stjr 631133819Stjrstatic void 632133819Stjrsetifnetmask(const char *addr, int dummy __unused, int s, 633133819Stjr const struct afswtch *afp) 634133819Stjr{ 635133819Stjr if (afp->af_getaddr != NULL) { 636133819Stjr setmask++; 637133819Stjr afp->af_getaddr(addr, MASK); 638133819Stjr } 639133819Stjr} 640133819Stjr 641133819Stjrstatic void 642133819Stjrsetifbroadaddr(const char *addr, int dummy __unused, int s, 643133819Stjr const struct afswtch *afp) 644133819Stjr{ 645133819Stjr if (afp->af_getaddr != NULL) 646133819Stjr afp->af_getaddr(addr, DSTADDR); 647133819Stjr} 648133819Stjr 649133819Stjrstatic void 650133819Stjrsetifipdst(const char *addr, int dummy __unused, int s, 651133819Stjr const struct afswtch *afp) 652133819Stjr{ 653133819Stjr const struct afswtch *inet; 654133819Stjr 655133819Stjr inet = af_getbyname("inet"); 656133819Stjr if (inet == NULL) 657133819Stjr return; 658133819Stjr inet->af_getaddr(addr, DSTADDR); 659133819Stjr clearaddr = 0; 660133819Stjr newaddr = 0; 661133819Stjr} 662133819Stjr 663133819Stjrstatic void 664133819Stjrnotealias(const char *addr, int param, int s, const struct afswtch *afp) 665133819Stjr{ 666133819Stjr#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 667133819Stjr if (setaddr && doalias == 0 && param < 0) 668133819Stjr if (afp->af_addreq != NULL && afp->af_ridreq != NULL) 669133819Stjr bcopy((caddr_t)rqtosa(af_addreq), 670133819Stjr (caddr_t)rqtosa(af_ridreq), 671133819Stjr rqtosa(af_addreq)->sa_len); 672133819Stjr doalias = param; 673133819Stjr if (param < 0) { 674133819Stjr clearaddr = 1; 675133819Stjr newaddr = 0; 676133819Stjr } else 677133819Stjr clearaddr = 0; 678133819Stjr#undef rqtosa 679133819Stjr} 680133819Stjr 681133819Stjr/*ARGSUSED*/ 682133819Stjrstatic void 683133819Stjrsetifdstaddr(const char *addr, int param __unused, int s, 684133819Stjr const struct afswtch *afp) 685133819Stjr{ 686161309Snetchild if (afp->af_getaddr != NULL) 687161309Snetchild afp->af_getaddr(addr, DSTADDR); 688161309Snetchild} 689133819Stjr 690133819Stjr/* 691133819Stjr * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 692133819Stjr * of the ifreq structure, which may confuse other parts of ifconfig. 693133819Stjr * Make a private copy so we can avoid that. 694133819Stjr */ 695133819Stjrstatic void 696133819Stjrsetifflags(const char *vname, int value, int s, const struct afswtch *afp) 697133819Stjr{ 698133819Stjr struct ifreq my_ifr; 699133819Stjr int flags; 700133819Stjr 701133819Stjr memset(&my_ifr, 0, sizeof(my_ifr)); 702133819Stjr (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); 703133819Stjr 704133819Stjr if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 705133819Stjr Perror("ioctl (SIOCGIFFLAGS)"); 706133819Stjr exit(1); 707133819Stjr } 708133819Stjr flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16); 709133819Stjr 710133819Stjr if (value < 0) { 711133819Stjr value = -value; 712133819Stjr flags &= ~value; 713133819Stjr } else 714133819Stjr flags |= value; 715133819Stjr my_ifr.ifr_flags = flags & 0xffff; 716133819Stjr my_ifr.ifr_flagshigh = flags >> 16; 717133819Stjr if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 718133819Stjr Perror(vname); 719133819Stjr} 720133819Stjr 721133819Stjrvoid 722133819Stjrsetifcap(const char *vname, int value, int s, const struct afswtch *afp) 723133819Stjr{ 724133819Stjr int flags; 725161309Snetchild 726161309Snetchild if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 727161309Snetchild Perror("ioctl (SIOCGIFCAP)"); 728161309Snetchild exit(1); 729161309Snetchild } 730161309Snetchild flags = ifr.ifr_curcap; 731161309Snetchild if (value < 0) { 732161309Snetchild value = -value; 733161309Snetchild flags &= ~value; 734161309Snetchild } else 735161309Snetchild flags |= value; 736161309Snetchild flags &= ifr.ifr_reqcap; 737177258Srdivacky ifr.ifr_reqcap = flags; 738177258Srdivacky if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 739177258Srdivacky Perror(vname); 740177258Srdivacky} 741177258Srdivacky 742171999Skibstatic void 743171999Skibsetifmetric(const char *val, int dummy __unused, int s, 744171999Skib const struct afswtch *afp) 745171999Skib{ 746171999Skib strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 747168036Sjkim ifr.ifr_metric = atoi(val); 748168036Sjkim if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 749168036Sjkim warn("ioctl (set metric)"); 750133819Stjr} 751133819Stjr 752133819Stjrstatic void 753161309Snetchildsetifmtu(const char *val, int dummy __unused, int s, 754161309Snetchild const struct afswtch *afp) 755161309Snetchild{ 756159801Snetchild strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 757159801Snetchild ifr.ifr_mtu = atoi(val); 758159801Snetchild if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 759159801Snetchild warn("ioctl (set mtu)"); 760159801Snetchild} 761159801Snetchild 762159801Snetchildstatic void 763159801Snetchildsetifname(const char *val, int dummy __unused, int s, 764159801Snetchild const struct afswtch *afp) 765159801Snetchild{ 766159801Snetchild char *newname; 767159801Snetchild 768159801Snetchild newname = strdup(val); 769159801Snetchild if (newname == NULL) { 770159801Snetchild warn("no memory to set ifname"); 771159801Snetchild return; 772161309Snetchild } 773159801Snetchild ifr.ifr_data = newname; 774159801Snetchild if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { 775159801Snetchild warn("ioctl (set name)"); 776159801Snetchild free(newname); 777159801Snetchild return; 778159801Snetchild } 779159801Snetchild strlcpy(name, newname, sizeof(name)); 780159801Snetchild free(newname); 781159801Snetchild} 782159801Snetchild 783159801Snetchild#define IFFBITS \ 784159801Snetchild"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 785159801Snetchild"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 786159801Snetchild"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP" 787159801Snetchild 788159801Snetchild#define IFCAPBITS \ 789159801Snetchild"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ 790161309Snetchild"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \ 791161309Snetchild"\21VLAN_HWFILTER" 792159801Snetchild 793159801Snetchild/* 794161309Snetchild * Print the status of the interface. If an address family was 795161309Snetchild * specified, show only it; otherwise, show them all. 796159801Snetchild */ 797159801Snetchildstatic void 798161309Snetchildstatus(const struct afswtch *afp, const struct sockaddr_dl *sdl, 799161309Snetchild struct ifaddrs *ifa) 800159801Snetchild{ 801159801Snetchild struct ifaddrs *ift; 802161309Snetchild int allfamilies, s; 803161309Snetchild struct ifstat ifs; 804161309Snetchild 805161309Snetchild if (afp == NULL) { 806159801Snetchild allfamilies = 1; 807159801Snetchild ifr.ifr_addr.sa_family = AF_LOCAL; 808161666Snetchild } else { 809172220Sdwmalone allfamilies = 0; 810161666Snetchild ifr.ifr_addr.sa_family = 811159801Snetchild afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af; 812159801Snetchild } 813159801Snetchild strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 814159801Snetchild 815159801Snetchild s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); 816161309Snetchild if (s < 0) 817161309Snetchild err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family); 818161309Snetchild 819159801Snetchild printf("%s: ", name); 820159801Snetchild printb("flags", ifa->ifa_flags, IFFBITS); 821165690Snetchild if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1) 822165690Snetchild printf(" metric %d", ifr.ifr_metric); 823159801Snetchild if (ioctl(s, SIOCGIFMTU, &ifr) != -1) 824159801Snetchild printf(" mtu %d", ifr.ifr_mtu); 825159801Snetchild putchar('\n'); 826159801Snetchild 827159801Snetchild if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { 828159801Snetchild if (ifr.ifr_curcap != 0) { 829159801Snetchild printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 830159801Snetchild putchar('\n'); 831159801Snetchild } 832159801Snetchild if (supmedia && ifr.ifr_reqcap != 0) { 833159801Snetchild printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS); 834159801Snetchild putchar('\n'); 835159801Snetchild } 836159801Snetchild } 837159801Snetchild 838159801Snetchild tunnel_status(s); 839159801Snetchild 840159801Snetchild for (ift = ifa; ift != NULL; ift = ift->ifa_next) { 841159801Snetchild if (ift->ifa_addr == NULL) 842159801Snetchild continue; 843159801Snetchild if (strcmp(ifa->ifa_name, ift->ifa_name) != 0) 844159801Snetchild continue; 845159801Snetchild if (allfamilies) { 846159801Snetchild const struct afswtch *p; 847159801Snetchild p = af_getbyfamily(ift->ifa_addr->sa_family); 848159801Snetchild if (p != NULL && p->af_status != NULL) 849159801Snetchild p->af_status(s, ift); 850159801Snetchild } else if (afp->af_af == ift->ifa_addr->sa_family) 851159801Snetchild afp->af_status(s, ift); 852159801Snetchild } 853159801Snetchild#if 0 854159801Snetchild if (allfamilies || afp->af_af == AF_LINK) { 855159801Snetchild const struct afswtch *lafp; 856159801Snetchild 857159801Snetchild /* 858159801Snetchild * Hack; the link level address is received separately 859159801Snetchild * from the routing information so any address is not 860159801Snetchild * handled above. Cobble together an entry and invoke 861159801Snetchild * the status method specially. 862159801Snetchild */ 863159801Snetchild lafp = af_getbyname("lladdr"); 864159801Snetchild if (lafp != NULL) { 865159801Snetchild info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl; 866159801Snetchild lafp->af_status(s, &info); 867159801Snetchild } 868159801Snetchild } 869159801Snetchild#endif 870159801Snetchild if (allfamilies) 871159801Snetchild af_other_status(s); 872159801Snetchild else if (afp->af_other_status != NULL) 873159801Snetchild afp->af_other_status(s); 874159801Snetchild 875159801Snetchild strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 876159801Snetchild if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 877159801Snetchild printf("%s", ifs.ascii); 878159801Snetchild 879159801Snetchild close(s); 880159801Snetchild return; 881159801Snetchild} 882159801Snetchild 883159801Snetchildstatic void 884159801Snetchildtunnel_status(int s) 885159801Snetchild{ 886159801Snetchild af_all_tunnel_status(s); 887159801Snetchild} 888168014Sjulian 889168014Sjulianvoid 890168014SjulianPerror(const char *cmd) 891168014Sjulian{ 892159801Snetchild switch (errno) { 893159801Snetchild 894159801Snetchild case ENXIO: 895159801Snetchild errx(1, "%s: no such interface", cmd); 896159801Snetchild break; 897159801Snetchild 898159801Snetchild case EPERM: 899159801Snetchild errx(1, "%s: permission denied", cmd); 900159801Snetchild break; 901159801Snetchild 902159801Snetchild default: 903159801Snetchild err(1, "%s", cmd); 904159801Snetchild } 905159801Snetchild} 906159801Snetchild 907159801Snetchild/* 908159801Snetchild * Print a value a la the %b format of the kernel's printf 909159801Snetchild */ 910159801Snetchildvoid 911159801Snetchildprintb(const char *s, unsigned v, const char *bits) 912159801Snetchild{ 913159801Snetchild int i, any = 0; 914159801Snetchild char c; 915159801Snetchild 916159801Snetchild if (bits && *bits == 8) 917159801Snetchild printf("%s=%o", s, v); 918159801Snetchild else 919159801Snetchild printf("%s=%x", s, v); 920159801Snetchild bits++; 921159801Snetchild if (bits) { 922159801Snetchild putchar('<'); 923159801Snetchild while ((i = *bits++) != '\0') { 924159801Snetchild if (v & (1 << (i-1))) { 925159801Snetchild if (any) 926159801Snetchild putchar(','); 927159801Snetchild any = 1; 928159801Snetchild for (; (c = *bits) > 32; bits++) 929159801Snetchild putchar(c); 930159801Snetchild } else 931159801Snetchild for (; *bits > 32; bits++) 932159801Snetchild ; 933159801Snetchild } 934159801Snetchild putchar('>'); 935159801Snetchild } 936159801Snetchild} 937159801Snetchild 938143198Ssobomaxvoid 939133819Stjrifmaybeload(const char *name) 940133819Stjr{ 941133819Stjr#define MOD_PREFIX_LEN 3 /* "if_" */ 942133819Stjr struct module_stat mstat; 943133819Stjr int fileid, modid; 944133819Stjr char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; 945133819Stjr const char *cp; 946133819Stjr 947133819Stjr /* loading suppressed by the user */ 948133819Stjr if (noload) 949133819Stjr return; 950133819Stjr 951156919Snetchild /* trim the interface number off the end */ 952133819Stjr strlcpy(ifname, name, sizeof(ifname)); 953133819Stjr for (dp = ifname; *dp != 0; dp++) 954133819Stjr if (isdigit(*dp)) { 955133819Stjr *dp = 0; 956133819Stjr break; 957133819Stjr } 958133819Stjr 959133819Stjr /* turn interface and unit into module name */ 960133819Stjr strcpy(ifkind, "if_"); 961133819Stjr strlcpy(ifkind + MOD_PREFIX_LEN, ifname, 962133819Stjr sizeof(ifkind) - MOD_PREFIX_LEN); 963133819Stjr 964133819Stjr /* scan files in kernel */ 965133819Stjr mstat.version = sizeof(struct module_stat); 966133819Stjr for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 967133819Stjr /* scan modules in file */ 968133819Stjr for (modid = kldfirstmod(fileid); modid > 0; 969133819Stjr modid = modfnext(modid)) { 970133819Stjr if (modstat(modid, &mstat) < 0) 971133819Stjr continue; 972133819Stjr /* strip bus name if present */ 973133819Stjr if ((cp = strchr(mstat.name, '/')) != NULL) { 974133819Stjr cp++; 975133819Stjr } else { 976133819Stjr cp = mstat.name; 977133819Stjr } 978133819Stjr /* already loaded? */ 979133819Stjr if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 || 980133819Stjr strncmp(ifkind, cp, strlen(ifkind) + 1) == 0) 981133819Stjr return; 982161309Snetchild } 983133819Stjr } 984133819Stjr 985133819Stjr /* not present, we should try to load it */ 986133819Stjr kldload(ifkind); 987133819Stjr} 988133819Stjr 989133819Stjrstatic struct cmd basic_cmds[] = { 990156843Snetchild DEF_CMD("up", IFF_UP, setifflags), 991133819Stjr DEF_CMD("down", -IFF_UP, setifflags), 992133819Stjr DEF_CMD("arp", -IFF_NOARP, setifflags), 993133819Stjr DEF_CMD("-arp", IFF_NOARP, setifflags), 994133819Stjr DEF_CMD("debug", IFF_DEBUG, setifflags), 995133819Stjr DEF_CMD("-debug", -IFF_DEBUG, setifflags), 996133819Stjr DEF_CMD("promisc", IFF_PPROMISC, setifflags), 997133819Stjr DEF_CMD("-promisc", -IFF_PPROMISC, setifflags), 998133819Stjr DEF_CMD("add", IFF_UP, notealias), 999133819Stjr DEF_CMD("alias", IFF_UP, notealias), 1000156919Snetchild DEF_CMD("-alias", -IFF_UP, notealias), 1001133819Stjr DEF_CMD("delete", -IFF_UP, notealias), 1002133819Stjr DEF_CMD("remove", -IFF_UP, notealias), 1003133819Stjr#ifdef notdef 1004133819Stjr#define EN_SWABIPS 0x1000 1005133819Stjr DEF_CMD("swabips", EN_SWABIPS, setifflags), 1006156843Snetchild DEF_CMD("-swabips", -EN_SWABIPS, setifflags), 1007147142Ssobomax#endif 1008133819Stjr DEF_CMD_ARG("netmask", setifnetmask), 1009133819Stjr DEF_CMD_ARG("metric", setifmetric), 1010133819Stjr DEF_CMD_ARG("broadcast", setifbroadaddr), 1011133819Stjr DEF_CMD_ARG("ipdst", setifipdst), 1012133819Stjr DEF_CMD_ARG2("tunnel", settunnel), 1013133819Stjr DEF_CMD("-tunnel", 0, deletetunnel), 1014133819Stjr DEF_CMD("deletetunnel", 0, deletetunnel), 1015133819Stjr DEF_CMD("link0", IFF_LINK0, setifflags), 1016133819Stjr DEF_CMD("-link0", -IFF_LINK0, setifflags), 1017133819Stjr DEF_CMD("link1", IFF_LINK1, setifflags), 1018166730Sjkim DEF_CMD("-link1", -IFF_LINK1, setifflags), 1019133819Stjr DEF_CMD("link2", IFF_LINK2, setifflags), 1020133819Stjr DEF_CMD("-link2", -IFF_LINK2, setifflags), 1021133819Stjr DEF_CMD("monitor", IFF_MONITOR, setifflags), 1022133819Stjr DEF_CMD("-monitor", -IFF_MONITOR, setifflags), 1023133819Stjr DEF_CMD("staticarp", IFF_STATICARP, setifflags), 1024133819Stjr DEF_CMD("-staticarp", -IFF_STATICARP, setifflags), 1025133819Stjr DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap), 1026133819Stjr DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap), 1027133819Stjr DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap), 1028133819Stjr DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap), 1029133819Stjr DEF_CMD("netcons", IFCAP_NETCONS, setifcap), 1030133819Stjr DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap), 1031133819Stjr DEF_CMD("polling", IFCAP_POLLING, setifcap), 1032133819Stjr DEF_CMD("-polling", -IFCAP_POLLING, setifcap), 1033133819Stjr DEF_CMD("tso", IFCAP_TSO, setifcap), 1034133819Stjr DEF_CMD("-tso", -IFCAP_TSO, setifcap), 1035133819Stjr DEF_CMD("lro", IFCAP_LRO, setifcap), 1036133819Stjr DEF_CMD("-lro", -IFCAP_LRO, setifcap), 1037133819Stjr DEF_CMD("wol", IFCAP_WOL, setifcap), 1038133819Stjr DEF_CMD("-wol", -IFCAP_WOL, setifcap), 1039133819Stjr DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap), 1040133819Stjr DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap), 1041133819Stjr DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap), 1042133819Stjr DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap), 1043133819Stjr DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap), 1044133819Stjr DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap), 1045133819Stjr DEF_CMD("normal", -IFF_LINK0, setifflags), 1046133819Stjr DEF_CMD("compress", IFF_LINK0, setifflags), 1047133819Stjr DEF_CMD("noicmp", IFF_LINK1, setifflags), 1048133819Stjr DEF_CMD_ARG("mtu", setifmtu), 1049133819Stjr DEF_CMD_ARG("name", setifname), 1050133819Stjr}; 1051133819Stjr 1052133819Stjrstatic __constructor void 1053133819Stjrifconfig_ctor(void) 1054133819Stjr{ 1055133819Stjr#define N(a) (sizeof(a) / sizeof(a[0])) 1056133819Stjr int i; 1057133819Stjr 1058133819Stjr for (i = 0; i < N(basic_cmds); i++) 1059133819Stjr cmd_register(&basic_cmds[i]); 1060133819Stjr#undef N 1061133819Stjr} 1062133819Stjr