ifconfig.c revision 128186
1139749Simp/* 2119853Scg * Copyright (c) 1983, 1993 350724Scg * The Regents of the University of California. All rights reserved. 450724Scg * 550724Scg * Redistribution and use in source and binary forms, with or without 650724Scg * modification, are permitted provided that the following conditions 750724Scg * are met: 850724Scg * 1. Redistributions of source code must retain the above copyright 950724Scg * notice, this list of conditions and the following disclaimer. 1050724Scg * 2. Redistributions in binary form must reproduce the above copyright 1150724Scg * notice, this list of conditions and the following disclaimer in the 1250724Scg * documentation and/or other materials provided with the distribution. 1350724Scg * 4. Neither the name of the University nor the names of its contributors 1450724Scg * may be used to endorse or promote products derived from this software 1550724Scg * without specific prior written permission. 1650724Scg * 1750724Scg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1850724Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1950724Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2050724Scg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2150724Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2250724Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2350724Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2450724Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2550724Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2650733Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2750724Scg * SUCH DAMAGE. 2850724Scg */ 2950724Scg 3050724Scg#ifndef lint 3150724Scgstatic const char copyright[] = 3250724Scg"@(#) Copyright (c) 1983, 1993\n\ 3350724Scg The Regents of the University of California. All rights reserved.\n"; 3450724Scg#endif /* not lint */ 3550724Scg 3650724Scg#ifndef lint 3750724Scg#if 0 3850724Scgstatic char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 3950724Scg#endif 4050724Scgstatic const char rcsid[] = 4150724Scg "$FreeBSD: head/sbin/ifconfig/ifconfig.c 128186 2004-04-13 11:24:43Z luigi $"; 4250724Scg#endif /* not lint */ 4350724Scg 4450724Scg#include <sys/param.h> 4550724Scg#include <sys/ioctl.h> 4650724Scg#include <sys/socket.h> 4750724Scg#include <sys/sysctl.h> 4850724Scg#include <sys/time.h> 4950724Scg#include <sys/module.h> 5050724Scg#include <sys/linker.h> 5150724Scg 5250724Scg#include <net/ethernet.h> 5350724Scg#include <net/if.h> 5450724Scg#include <net/if_var.h> 5550724Scg#include <net/if_dl.h> 5650724Scg#include <net/if_types.h> 5750724Scg#include <net/route.h> 5850724Scg 5950724Scg/* IP */ 6050724Scg#include <netinet/in.h> 6150724Scg#include <netinet/in_var.h> 6250724Scg#include <arpa/inet.h> 6350724Scg#include <netdb.h> 6450724Scg 6550724Scg#ifdef INET6 6682363Sgreid#include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */ 6782363Sgreid#endif 6882363Sgreid 6982363Sgreid#ifndef NO_IPX 7082363Sgreid/* IPX */ 7182363Sgreid#define IPXIP 7282363Sgreid#define IPTUNNEL 7350724Scg#include <netipx/ipx.h> 7450724Scg#include <netipx/ipx_if.h> 7550724Scg#endif 7650724Scg 7750724Scg/* Appletalk */ 7850724Scg#include <netatalk/at.h> 7950724Scg 8050724Scg#include <ctype.h> 8150724Scg#include <err.h> 8250724Scg#include <errno.h> 8350724Scg#include <fcntl.h> 8450724Scg#include <stdio.h> 8550724Scg#include <stdlib.h> 8650724Scg#include <string.h> 8750724Scg#include <unistd.h> 8850724Scg#include <ifaddrs.h> 8950724Scg 9050724Scg#include "ifconfig.h" 9171503Scg 9250724Scg/* wrapper for KAME-special getnameinfo() */ 9350724Scg#ifndef NI_WITHSCOPEID 9450724Scg#define NI_WITHSCOPEID 0 9550724Scg#endif 9650724Scg 9771503Scgstruct ifreq ifr, ridreq; 9850724Scgstruct ifaliasreq addreq; 9950724Scg#ifdef INET6 10050724Scgstruct in6_ifreq in6_ridreq; 10150724Scgstruct in6_aliasreq in6_addreq = 10250724Scg { { 0 }, 10350724Scg { 0 }, 10450724Scg { 0 }, 105 { 0 }, 106 0, 107 { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; 108#endif 109struct sockaddr_in netmask; 110struct netrange at_nr; /* AppleTalk net range */ 111 112char name[IFNAMSIZ]; 113int flags; 114int setaddr; 115int setipdst; 116int setmask; 117int doalias; 118int clearaddr; 119int newaddr = 1; 120#ifdef INET6 121static int ip6lifetime; 122#endif 123 124struct afswtch; 125 126int supmedia = 0; 127int listcloners = 0; 128int printname = 0; /* Print the name of the created interface. */ 129 130#ifdef INET6 131char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/ 132#endif 133 134void Perror(const char *cmd); 135void checkatrange(struct sockaddr_at *); 136int ifconfig(int argc, char *const *argv, const struct afswtch *afp); 137void notealias(const char *, int, int, const struct afswtch *afp); 138void list_cloners(void); 139void printb(const char *s, unsigned value, const char *bits); 140void rt_xaddrs(caddr_t, caddr_t, struct rt_addrinfo *); 141void status(const struct afswtch *afp, int addrcount, 142 struct sockaddr_dl *sdl, struct if_msghdr *ifm, 143 struct ifa_msghdr *ifam); 144void tunnel_status(int s); 145void usage(void); 146void ifmaybeload(char *name); 147 148#ifdef INET6 149void in6_fillscopeid(struct sockaddr_in6 *sin6); 150int prefix(void *, int); 151static char *sec2str(time_t); 152int explicit_prefix = 0; 153#endif 154 155typedef void c_func(const char *cmd, int arg, int s, const struct afswtch *afp); 156typedef void c_func2(const char *arg, const char *arg2, int s, const struct afswtch *afp); 157c_func setatphase, setatrange; 158c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask; 159c_func2 settunnel; 160c_func deletetunnel; 161#ifdef INET6 162c_func setifprefixlen; 163c_func setip6flags; 164c_func setip6pltime; 165c_func setip6vltime; 166c_func2 setip6lifetime; 167c_func setip6eui64; 168#endif 169c_func setifipdst; 170c_func setifflags, setifmetric, setifmtu, setifcap; 171c_func clone_destroy; 172c_func setifname; 173 174 175void clone_create(void); 176 177 178#define NEXTARG 0xffffff 179#define NEXTARG2 0xfffffe 180 181const 182struct cmd { 183 const char *c_name; 184 int c_parameter; /* NEXTARG means next argv */ 185 void (*c_func)(const char *, int, int, const struct afswtch *afp); 186 void (*c_func2)(const char *, const char *, int, const struct afswtch *afp); 187} cmds[] = { 188 { "up", IFF_UP, setifflags } , 189 { "down", -IFF_UP, setifflags }, 190 { "arp", -IFF_NOARP, setifflags }, 191 { "-arp", IFF_NOARP, setifflags }, 192 { "debug", IFF_DEBUG, setifflags }, 193 { "-debug", -IFF_DEBUG, setifflags }, 194 { "promisc", IFF_PPROMISC, setifflags }, 195 { "-promisc", -IFF_PPROMISC, setifflags }, 196 { "add", IFF_UP, notealias }, 197 { "alias", IFF_UP, notealias }, 198 { "-alias", -IFF_UP, notealias }, 199 { "delete", -IFF_UP, notealias }, 200 { "remove", -IFF_UP, notealias }, 201#ifdef notdef 202#define EN_SWABIPS 0x1000 203 { "swabips", EN_SWABIPS, setifflags }, 204 { "-swabips", -EN_SWABIPS, setifflags }, 205#endif 206 { "netmask", NEXTARG, setifnetmask }, 207#ifdef INET6 208 { "prefixlen", NEXTARG, setifprefixlen }, 209 { "anycast", IN6_IFF_ANYCAST, setip6flags }, 210 { "tentative", IN6_IFF_TENTATIVE, setip6flags }, 211 { "-tentative", -IN6_IFF_TENTATIVE, setip6flags }, 212 { "deprecated", IN6_IFF_DEPRECATED, setip6flags }, 213 { "-deprecated", -IN6_IFF_DEPRECATED, setip6flags }, 214 { "autoconf", IN6_IFF_AUTOCONF, setip6flags }, 215 { "-autoconf", -IN6_IFF_AUTOCONF, setip6flags }, 216 { "pltime", NEXTARG, setip6pltime }, 217 { "vltime", NEXTARG, setip6vltime }, 218 { "eui64", 0, setip6eui64 }, 219#endif 220 { "range", NEXTARG, setatrange }, 221 { "phase", NEXTARG, setatphase }, 222 { "metric", NEXTARG, setifmetric }, 223 { "broadcast", NEXTARG, setifbroadaddr }, 224 { "ipdst", NEXTARG, setifipdst }, 225 { "tunnel", NEXTARG2, NULL, settunnel }, 226 { "deletetunnel", 0, deletetunnel }, 227 { "link0", IFF_LINK0, setifflags }, 228 { "-link0", -IFF_LINK0, setifflags }, 229 { "link1", IFF_LINK1, setifflags }, 230 { "-link1", -IFF_LINK1, setifflags }, 231 { "link2", IFF_LINK2, setifflags }, 232 { "-link2", -IFF_LINK2, setifflags }, 233 { "monitor", IFF_MONITOR, setifflags }, 234 { "-monitor", -IFF_MONITOR, setifflags }, 235 { "staticarp", IFF_STATICARP, setifflags }, 236 { "-staticarp", -IFF_STATICARP, setifflags }, 237#ifdef USE_IF_MEDIA 238 { "media", NEXTARG, setmedia }, 239 { "mode", NEXTARG, setmediamode }, 240 { "mediaopt", NEXTARG, setmediaopt }, 241 { "-mediaopt", NEXTARG, unsetmediaopt }, 242#endif 243#ifdef USE_VLANS 244 { "vlan", NEXTARG, setvlantag }, 245 { "vlandev", NEXTARG, setvlandev }, 246 { "-vlandev", NEXTARG, unsetvlandev }, 247#endif 248#if 0 249 /* XXX `create' special-cased below */ 250 {"create", 0, clone_create }, 251 {"plumb", 0, clone_create }, 252#endif 253 {"destroy", 0, clone_destroy }, 254 {"unplumb", 0, clone_destroy }, 255#ifdef USE_IEEE80211 256 { "ssid", NEXTARG, set80211ssid }, 257 { "nwid", NEXTARG, set80211ssid }, 258 { "stationname", NEXTARG, set80211stationname }, 259 { "station", NEXTARG, set80211stationname }, /* BSD/OS */ 260 { "channel", NEXTARG, set80211channel }, 261 { "authmode", NEXTARG, set80211authmode }, 262 { "powersavemode", NEXTARG, set80211powersavemode }, 263 { "powersave", 1, set80211powersave }, 264 { "-powersave", 0, set80211powersave }, 265 { "powersavesleep", NEXTARG, set80211powersavesleep }, 266 { "wepmode", NEXTARG, set80211wepmode }, 267 { "wep", 1, set80211wep }, 268 { "-wep", 0, set80211wep }, 269 { "weptxkey", NEXTARG, set80211weptxkey }, 270 { "wepkey", NEXTARG, set80211wepkey }, 271 { "nwkey", NEXTARG, set80211nwkey }, /* NetBSD */ 272 { "-nwkey", 0, set80211wep }, /* NetBSD */ 273 { "rtsthreshold",NEXTARG, set80211rtsthreshold }, 274 { "protmode", NEXTARG, set80211protmode }, 275 { "txpower", NEXTARG, set80211txpower }, 276#endif 277#ifdef USE_MAC 278 { "maclabel", NEXTARG, setifmaclabel }, 279#endif 280 { "rxcsum", IFCAP_RXCSUM, setifcap }, 281 { "-rxcsum", -IFCAP_RXCSUM, setifcap }, 282 { "txcsum", IFCAP_TXCSUM, setifcap }, 283 { "-txcsum", -IFCAP_TXCSUM, setifcap }, 284 { "netcons", IFCAP_NETCONS, setifcap }, 285 { "-netcons", -IFCAP_NETCONS, setifcap }, 286 { "polling", IFCAP_POLLING, setifcap }, 287 { "-polling", -IFCAP_POLLING, setifcap }, 288 { "normal", -IFF_LINK0, setifflags }, 289 { "compress", IFF_LINK0, setifflags }, 290 { "noicmp", IFF_LINK1, setifflags }, 291 { "mtu", NEXTARG, setifmtu }, 292 { "name", NEXTARG, setifname }, 293 { 0, 0, setifaddr }, 294 { 0, 0, setifdstaddr }, 295}; 296 297/* 298 * XNS support liberally adapted from code written at the University of 299 * Maryland principally by James O'Toole and Chris Torek. 300 */ 301typedef void af_status(int, struct rt_addrinfo *); 302typedef void af_getaddr(const char *, int); 303typedef void af_getprefix(const char *, int); 304 305af_status in_status, at_status, link_status; 306af_getaddr in_getaddr, at_getaddr, link_getaddr; 307 308#ifndef NO_IPX 309af_status ipx_status; 310af_getaddr ipx_getaddr; 311#endif 312 313#ifdef INET6 314af_status in6_status; 315af_getaddr in6_getaddr; 316af_getprefix in6_getprefix; 317#endif /*INET6*/ 318 319/* Known address families */ 320const 321struct afswtch { 322 const char *af_name; 323 short af_af; 324 af_status *af_status; 325 af_getaddr *af_getaddr; 326 af_getprefix *af_getprefix; 327 u_long af_difaddr; 328 u_long af_aifaddr; 329 caddr_t af_ridreq; 330 caddr_t af_addreq; 331} afs[] = { 332#define C(x) ((caddr_t) &x) 333 { "inet", AF_INET, in_status, in_getaddr, NULL, 334 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 335#ifdef INET6 336 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 337 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 338 C(in6_ridreq), C(in6_addreq) }, 339#endif /*INET6*/ 340#ifndef NO_IPX 341 { "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL, 342 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 343#endif 344 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 345 SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) }, 346 { "link", AF_LINK, link_status, link_getaddr, NULL, 347 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 348 { "ether", AF_LINK, link_status, link_getaddr, NULL, 349 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 350 { "lladdr", AF_LINK, link_status, link_getaddr, NULL, 351 0, SIOCSIFLLADDR, NULL, C(ridreq) }, 352#if 0 /* XXX conflicts with the media command */ 353#ifdef USE_IF_MEDIA 354 { "media", AF_UNSPEC, media_status, NULL, NULL, }, /* XXX not real!! */ 355#endif 356#ifdef USE_VLANS 357 { "vlan", AF_UNSPEC, vlan_status, NULL, NULL, }, /* XXX not real!! */ 358#endif 359#ifdef USE_IEEE80211 360 { "ieee80211", AF_UNSPEC, ieee80211_status, NULL, NULL, }, /* XXX not real!! */ 361#endif 362#ifdef USE_MAC 363 { "maclabel", AF_UNSPEC, maclabel_status, NULL, NULL, }, 364#endif 365#endif 366 { 0, 0, 0, 0 } 367}; 368 369/* 370 * Expand the compacted form of addresses as returned via the 371 * configuration read via sysctl(). 372 */ 373 374void 375rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) 376{ 377 struct sockaddr *sa; 378 int i; 379 380 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); 381 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { 382 if ((rtinfo->rti_addrs & (1 << i)) == 0) 383 continue; 384 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; 385 cp += SA_SIZE(sa); 386 } 387} 388 389 390void 391usage(void) 392{ 393#ifndef INET6 394 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 395 "usage: ifconfig interface address_family [address [dest_address]]", 396 " [parameters]", 397 " ifconfig -C", 398 " ifconfig interface create", 399 " ifconfig -a [-d] [-m] [-u] [address_family]", 400 " ifconfig -l [-d] [-u] [address_family]", 401 " ifconfig [-d] [-m] [-u]"); 402#else 403 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 404 "usage: ifconfig [-L] interface address_family [address [dest_address]]", 405 " [parameters]", 406 " ifconfig -C", 407 " ifconfig interface create", 408 " ifconfig -a [-L] [-d] [-m] [-u] [address_family]", 409 " ifconfig -l [-d] [-u] [address_family]", 410 " ifconfig [-L] [-d] [-m] [-u]"); 411#endif 412 exit(1); 413} 414 415int 416main(int argc, char *argv[]) 417{ 418 int c; 419 int all, namesonly, downonly, uponly; 420 int need_nl = 0; 421 const struct afswtch *afp = 0; 422 int addrcount, ifindex; 423 struct if_msghdr *ifm, *nextifm; 424 struct ifa_msghdr *ifam; 425 struct sockaddr_dl *sdl; 426 char *buf, *lim, *next; 427 size_t needed; 428 int mib[6]; 429 430 /* Parse leading line options */ 431 all = downonly = uponly = namesonly = 0; 432 while ((c = getopt(argc, argv, "adlmuC" 433#ifdef INET6 434 "L" 435#endif 436 )) != -1) { 437 switch (c) { 438 case 'a': /* scan all interfaces */ 439 all++; 440 break; 441 case 'd': /* restrict scan to "down" interfaces */ 442 downonly++; 443 break; 444 case 'l': /* scan interface names only */ 445 namesonly++; 446 break; 447 case 'm': /* show media choices in status */ 448 supmedia = 1; 449 break; 450 case 'u': /* restrict scan to "up" interfaces */ 451 uponly++; 452 break; 453 case 'C': 454 listcloners = 1; 455 break; 456#ifdef INET6 457 case 'L': 458 ip6lifetime++; /* print IPv6 address lifetime */ 459 break; 460#endif 461 default: 462 usage(); 463 break; 464 } 465 } 466 argc -= optind; 467 argv += optind; 468 469 if (listcloners) { 470 /* -C must be solitary */ 471 if (all || supmedia || uponly || downonly || namesonly || 472 argc > 0) 473 usage(); 474 475 list_cloners(); 476 exit(0); 477 } 478 479 /* -l cannot be used with -a or -m */ 480 if (namesonly && (all || supmedia)) 481 usage(); 482 483 /* nonsense.. */ 484 if (uponly && downonly) 485 usage(); 486 487 /* no arguments is equivalent to '-a' */ 488 if (!namesonly && argc < 1) 489 all = 1; 490 491 /* -a and -l allow an address family arg to limit the output */ 492 if (all || namesonly) { 493 if (argc > 1) 494 usage(); 495 496 ifindex = 0; 497 if (argc == 1) { 498 for (afp = afs; afp->af_name; afp++) 499 if (strcmp(afp->af_name, *argv) == 0) { 500 argc--, argv++; 501 break; 502 } 503 if (afp->af_name == NULL) 504 usage(); 505 /* leave with afp non-zero */ 506 } 507 } else { 508 /* not listing, need an argument */ 509 if (argc < 1) 510 usage(); 511 512 strncpy(name, *argv, sizeof(name)); 513 argc--, argv++; 514 515 /* check and maybe load support for this interface */ 516 ifmaybeload(name); 517 518 /* 519 * NOTE: We must special-case the `create' command right 520 * here as we would otherwise fail when trying to find 521 * the interface. 522 */ 523 if (argc > 0 && (strcmp(argv[0], "create") == 0 || 524 strcmp(argv[0], "plumb") == 0)) { 525 clone_create(); 526 argc--, argv++; 527 if (argc == 0) 528 goto end; 529 } 530 ifindex = if_nametoindex(name); 531 if (ifindex == 0) 532 errx(1, "interface %s does not exist", name); 533 } 534 535 /* Check for address family */ 536 if (argc > 0) { 537 for (afp = afs; afp->af_name; afp++) 538 if (strcmp(afp->af_name, *argv) == 0) { 539 argc--, argv++; 540 break; 541 } 542 if (afp->af_name == NULL) 543 afp = NULL; /* not a family, NULL */ 544 } 545 546 mib[0] = CTL_NET; 547 mib[1] = PF_ROUTE; 548 mib[2] = 0; 549 mib[3] = 0; /* address family */ 550 mib[4] = NET_RT_IFLIST; 551 mib[5] = ifindex; /* interface index */ 552 553 /* if particular family specified, only ask about it */ 554 if (afp) 555 mib[3] = afp->af_af; 556 557 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 558 errx(1, "iflist-sysctl-estimate"); 559 if ((buf = malloc(needed)) == NULL) 560 errx(1, "malloc"); 561 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 562 errx(1, "actual retrieval of interface table"); 563 lim = buf + needed; 564 565 next = buf; 566 while (next < lim) { 567 568 ifm = (struct if_msghdr *)next; 569 570 if (ifm->ifm_type == RTM_IFINFO) { 571 sdl = (struct sockaddr_dl *)(ifm + 1); 572 flags = ifm->ifm_flags; 573 } else { 574 fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n"); 575 fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, 576 ifm->ifm_type); 577 fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); 578 fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, 579 lim); 580 exit (1); 581 } 582 583 next += ifm->ifm_msglen; 584 ifam = NULL; 585 addrcount = 0; 586 while (next < lim) { 587 588 nextifm = (struct if_msghdr *)next; 589 590 if (nextifm->ifm_type != RTM_NEWADDR) 591 break; 592 593 if (ifam == NULL) 594 ifam = (struct ifa_msghdr *)nextifm; 595 596 addrcount++; 597 next += nextifm->ifm_msglen; 598 } 599 memcpy(name, sdl->sdl_data, 600 sizeof(name) < sdl->sdl_nlen ? 601 sizeof(name)-1 : sdl->sdl_nlen); 602 name[sizeof(name) < sdl->sdl_nlen ? 603 sizeof(name)-1 : sdl->sdl_nlen] = '\0'; 604 605 if (all || namesonly) { 606 if (uponly) 607 if ((flags & IFF_UP) == 0) 608 continue; /* not up */ 609 if (downonly) 610 if (flags & IFF_UP) 611 continue; /* not down */ 612 if (namesonly) { 613 if (afp == NULL || 614 afp->af_status != link_status || 615 sdl->sdl_type == IFT_ETHER) { 616 if (need_nl) 617 putchar(' '); 618 fputs(name, stdout); 619 need_nl++; 620 } 621 continue; 622 } 623 } 624 625 if (argc > 0) 626 ifconfig(argc, argv, afp); 627 else 628 status(afp, addrcount, sdl, ifm, ifam); 629 } 630 free(buf); 631 632 if (namesonly && need_nl > 0) 633 putchar('\n'); 634end: 635 if (printname) 636 printf("%s\n", name); 637 638 exit (0); 639} 640 641int 642ifconfig(int argc, char *const *argv, const struct afswtch *afp) 643{ 644 int s; 645 646 if (afp == NULL) 647 afp = &afs[0]; 648 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 649 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 650 651 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 652 err(1, "socket"); 653 654 while (argc > 0) { 655 const struct cmd *p; 656 657 for (p = cmds; p->c_name; p++) 658 if (strcmp(*argv, p->c_name) == 0) 659 break; 660 if (p->c_name == 0 && setaddr) 661 p++; /* got src, do dst */ 662 if (p->c_func || p->c_func2) { 663 if (p->c_parameter == NEXTARG) { 664 if (argv[1] == NULL) 665 errx(1, "'%s' requires argument", 666 p->c_name); 667 (*p->c_func)(argv[1], 0, s, afp); 668 argc--, argv++; 669 } else if (p->c_parameter == NEXTARG2) { 670 if (argc < 3) 671 errx(1, "'%s' requires 2 arguments", 672 p->c_name); 673 (*p->c_func2)(argv[1], argv[2], s, afp); 674 argc -= 2, argv += 2; 675 } else 676 (*p->c_func)(*argv, p->c_parameter, s, afp); 677 } 678 argc--, argv++; 679 } 680#ifdef INET6 681 if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) { 682 /* Aggregatable address architecture defines all prefixes 683 are 64. So, it is convenient to set prefixlen to 64 if 684 it is not specified. */ 685 setifprefixlen("64", 0, s, afp); 686 /* in6_getprefix("64", MASK) if MASK is available here... */ 687 } 688#endif 689#ifndef NO_IPX 690 if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) { 691 struct ipxip_req rq; 692 int size = sizeof(rq); 693 694 rq.rq_ipx = addreq.ifra_addr; 695 rq.rq_ip = addreq.ifra_dstaddr; 696 697 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 698 Perror("Encapsulation Routing"); 699 } 700#endif 701 if (ifr.ifr_addr.sa_family == AF_APPLETALK) 702 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 703 if (clearaddr) { 704 if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { 705 warnx("interface %s cannot change %s addresses!", 706 name, afp->af_name); 707 clearaddr = 0; 708 } 709 } 710 if (clearaddr) { 711 int ret; 712 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 713 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { 714 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 715 /* means no previous address for interface */ 716 } else 717 Perror("ioctl (SIOCDIFADDR)"); 718 } 719 } 720 if (newaddr) { 721 if (afp->af_addreq == NULL || afp->af_aifaddr == 0) { 722 warnx("interface %s cannot change %s addresses!", 723 name, afp->af_name); 724 newaddr = 0; 725 } 726 } 727 if (newaddr && (setaddr || setmask)) { 728 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 729 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 730 Perror("ioctl (SIOCAIFADDR)"); 731 } 732 close(s); 733 return(0); 734} 735#define RIDADDR 0 736#define ADDR 1 737#define MASK 2 738#define DSTADDR 3 739 740/*ARGSUSED*/ 741void 742setifaddr(const char *addr, int param, int s, const struct afswtch *afp) 743{ 744 if (*afp->af_getaddr == NULL) 745 return; 746 /* 747 * Delay the ioctl to set the interface addr until flags are all set. 748 * The address interpretation may depend on the flags, 749 * and the flags may change when the address is set. 750 */ 751 setaddr++; 752 if (doalias == 0 && afp->af_af != AF_LINK) 753 clearaddr = 1; 754 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 755} 756 757void 758settunnel(const char *src, const char *dst, int s, const struct afswtch *afp) 759{ 760 struct addrinfo hints, *srcres, *dstres; 761 struct ifaliasreq addreq; 762 int ecode; 763#ifdef INET6 764 struct in6_aliasreq in6_addreq; 765#endif 766 767 memset(&hints, 0, sizeof(hints)); 768 hints.ai_family = afp->af_af; 769 770 if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0) 771 errx(1, "error in parsing address string: %s", 772 gai_strerror(ecode)); 773 774 if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0) 775 errx(1, "error in parsing address string: %s", 776 gai_strerror(ecode)); 777 778 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 779 errx(1, 780 "source and destination address families do not match"); 781 782 switch (srcres->ai_addr->sa_family) { 783 case AF_INET: 784 memset(&addreq, 0, sizeof(addreq)); 785 strncpy(addreq.ifra_name, name, IFNAMSIZ); 786 memcpy(&addreq.ifra_addr, srcres->ai_addr, 787 srcres->ai_addr->sa_len); 788 memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, 789 dstres->ai_addr->sa_len); 790 791 if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0) 792 warn("SIOCSIFPHYADDR"); 793 break; 794 795#ifdef INET6 796 case AF_INET6: 797 memset(&in6_addreq, 0, sizeof(in6_addreq)); 798 strncpy(in6_addreq.ifra_name, name, IFNAMSIZ); 799 memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, 800 srcres->ai_addr->sa_len); 801 memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr, 802 dstres->ai_addr->sa_len); 803 804 if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0) 805 warn("SIOCSIFPHYADDR_IN6"); 806 break; 807#endif /* INET6 */ 808 809 default: 810 warn("address family not supported"); 811 } 812 813 freeaddrinfo(srcres); 814 freeaddrinfo(dstres); 815} 816 817/* ARGSUSED */ 818void 819deletetunnel(const char *vname, int param, int s, const struct afswtch *afp) 820{ 821 822 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 823 err(1, "SIOCDIFPHYADDR"); 824} 825 826void 827setifnetmask(const char *addr, int dummy __unused, int s, 828 const struct afswtch *afp) 829{ 830 if (*afp->af_getaddr == NULL) 831 return; 832 setmask++; 833 (*afp->af_getaddr)(addr, MASK); 834} 835 836#ifdef INET6 837void 838setifprefixlen(const char *addr, int dummy __unused, int s, 839 const struct afswtch *afp) 840{ 841 if (*afp->af_getprefix) 842 (*afp->af_getprefix)(addr, MASK); 843 explicit_prefix = 1; 844} 845 846void 847setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused, 848 const struct afswtch *afp) 849{ 850 if (afp->af_af != AF_INET6) 851 err(1, "address flags can be set only for inet6 addresses"); 852 853 if (flag < 0) 854 in6_addreq.ifra_flags &= ~(-flag); 855 else 856 in6_addreq.ifra_flags |= flag; 857} 858 859void 860setip6pltime(const char *seconds, int dummy __unused, int s, 861 const struct afswtch *afp) 862{ 863 setip6lifetime("pltime", seconds, s, afp); 864} 865 866void 867setip6vltime(const char *seconds, int dummy __unused, int s, 868 const struct afswtch *afp) 869{ 870 setip6lifetime("vltime", seconds, s, afp); 871} 872 873void 874setip6lifetime(const char *cmd, const char *val, int s, 875 const struct afswtch *afp) 876{ 877 time_t newval, t; 878 char *ep; 879 880 t = time(NULL); 881 newval = (time_t)strtoul(val, &ep, 0); 882 if (val == ep) 883 errx(1, "invalid %s", cmd); 884 if (afp->af_af != AF_INET6) 885 errx(1, "%s not allowed for the AF", cmd); 886 if (strcmp(cmd, "vltime") == 0) { 887 in6_addreq.ifra_lifetime.ia6t_expire = t + newval; 888 in6_addreq.ifra_lifetime.ia6t_vltime = newval; 889 } else if (strcmp(cmd, "pltime") == 0) { 890 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; 891 in6_addreq.ifra_lifetime.ia6t_pltime = newval; 892 } 893} 894 895void 896setip6eui64(const char *cmd, int dummy __unused, int s, 897 const struct afswtch *afp) 898{ 899 struct ifaddrs *ifap, *ifa; 900 const struct sockaddr_in6 *sin6 = NULL; 901 const struct in6_addr *lladdr = NULL; 902 struct in6_addr *in6; 903 904 if (afp->af_af != AF_INET6) 905 errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); 906 in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; 907 if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) 908 errx(EXIT_FAILURE, "interface index is already filled"); 909 if (getifaddrs(&ifap) != 0) 910 err(EXIT_FAILURE, "getifaddrs"); 911 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 912 if (ifa->ifa_addr->sa_family == AF_INET6 && 913 strcmp(ifa->ifa_name, name) == 0) { 914 sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; 915 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 916 lladdr = &sin6->sin6_addr; 917 break; 918 } 919 } 920 } 921 if (!lladdr) 922 errx(EXIT_FAILURE, "could not determine link local address"); 923 924 memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); 925 926 freeifaddrs(ifap); 927} 928#endif 929 930void 931setifbroadaddr(const char *addr, int dummy __unused, int s, 932 const struct afswtch *afp) 933{ 934 if (*afp->af_getaddr == NULL) 935 return; 936 (*afp->af_getaddr)(addr, DSTADDR); 937} 938 939void 940setifipdst(const char *addr, int dummy __unused, int s, 941 const struct afswtch *afp) 942{ 943 in_getaddr(addr, DSTADDR); 944 setipdst++; 945 clearaddr = 0; 946 newaddr = 0; 947} 948#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 949 950void 951notealias(const char *addr, int param, int s, const struct afswtch *afp) 952{ 953 if (setaddr && doalias == 0 && param < 0) 954 if (afp->af_addreq != NULL && afp->af_ridreq != NULL) 955 bcopy((caddr_t)rqtosa(af_addreq), 956 (caddr_t)rqtosa(af_ridreq), 957 rqtosa(af_addreq)->sa_len); 958 doalias = param; 959 if (param < 0) { 960 clearaddr = 1; 961 newaddr = 0; 962 } else 963 clearaddr = 0; 964} 965 966/*ARGSUSED*/ 967void 968setifdstaddr(const char *addr, int param __unused, int s, 969 const struct afswtch *afp) 970{ 971 if (*afp->af_getaddr == NULL) 972 return; 973 (*afp->af_getaddr)(addr, DSTADDR); 974} 975 976/* 977 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 978 * of the ifreq structure, which may confuse other parts of ifconfig. 979 * Make a private copy so we can avoid that. 980 */ 981void 982setifflags(const char *vname, int value, int s, const struct afswtch *afp) 983{ 984 struct ifreq my_ifr; 985 986 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 987 988 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) { 989 Perror("ioctl (SIOCGIFFLAGS)"); 990 exit(1); 991 } 992 strncpy(my_ifr.ifr_name, name, sizeof (my_ifr.ifr_name)); 993 flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16); 994 995 if (value < 0) { 996 value = -value; 997 flags &= ~value; 998 } else 999 flags |= value; 1000 my_ifr.ifr_flags = flags & 0xffff; 1001 my_ifr.ifr_flagshigh = flags >> 16; 1002 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 1003 Perror(vname); 1004} 1005 1006void 1007setifcap(const char *vname, int value, int s, const struct afswtch *afp) 1008{ 1009 1010 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) { 1011 Perror("ioctl (SIOCGIFCAP)"); 1012 exit(1); 1013 } 1014 flags = ifr.ifr_curcap; 1015 if (value < 0) { 1016 value = -value; 1017 flags &= ~value; 1018 } else 1019 flags |= value; 1020 ifr.ifr_reqcap = flags; 1021 if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0) 1022 Perror(vname); 1023} 1024 1025void 1026setifmetric(const char *val, int dummy __unused, int s, 1027 const struct afswtch *afp) 1028{ 1029 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1030 ifr.ifr_metric = atoi(val); 1031 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 1032 warn("ioctl (set metric)"); 1033} 1034 1035void 1036setifmtu(const char *val, int dummy __unused, int s, 1037 const struct afswtch *afp) 1038{ 1039 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1040 ifr.ifr_mtu = atoi(val); 1041 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 1042 warn("ioctl (set mtu)"); 1043} 1044 1045void 1046setifname(const char *val, int dummy __unused, int s, 1047 const struct afswtch *afp) 1048{ 1049 char *newname; 1050 1051 newname = strdup(val); 1052 1053 ifr.ifr_data = newname; 1054 if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { 1055 warn("ioctl (set name)"); 1056 free(newname); 1057 return; 1058 } 1059 strlcpy(name, newname, sizeof(name)); 1060 free(newname); 1061 1062 /* 1063 * Even if we just created the interface, we don't need to print 1064 * its name because we just nailed it down separately. 1065 */ 1066 printname = 0; 1067} 1068 1069#define IFFBITS \ 1070"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \ 1071"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ 1072"\20MULTICAST\21POLLING\23MONITOR\24STATICARP" 1073 1074#define IFCAPBITS \ 1075"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" 1076 1077/* 1078 * Print the status of the interface. If an address family was 1079 * specified, show it and it only; otherwise, show them all. 1080 */ 1081void 1082status(const struct afswtch *afp, int addrcount, struct sockaddr_dl *sdl, 1083 struct if_msghdr *ifm, struct ifa_msghdr *ifam) 1084{ 1085 const struct afswtch *p = NULL; 1086 struct rt_addrinfo info; 1087 int allfamilies, s; 1088 struct ifstat ifs; 1089 1090 if (afp == NULL) { 1091 allfamilies = 1; 1092 afp = &afs[0]; 1093 } else 1094 allfamilies = 0; 1095 1096 ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af; 1097 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1098 1099 if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) 1100 err(1, "socket"); 1101 1102 printf("%s: ", name); 1103 printb("flags", flags, IFFBITS); 1104 if (ifm->ifm_data.ifi_metric) 1105 printf(" metric %ld", ifm->ifm_data.ifi_metric); 1106 if (ifm->ifm_data.ifi_mtu) 1107 printf(" mtu %ld", ifm->ifm_data.ifi_mtu); 1108 putchar('\n'); 1109 1110 if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) { 1111 if (ifr.ifr_curcap != 0) { 1112 printb("\toptions", ifr.ifr_curcap, IFCAPBITS); 1113 putchar('\n'); 1114 } 1115 if (supmedia && ifr.ifr_reqcap != 0) { 1116 printf("\tcapability list:\n"); 1117 printb("\t\t", ifr.ifr_reqcap, IFCAPBITS); 1118 putchar('\n'); 1119 } 1120 } 1121 1122 tunnel_status(s); 1123 1124 while (addrcount > 0) { 1125 1126 info.rti_addrs = ifam->ifam_addrs; 1127 1128 /* Expand the compacted addresses */ 1129 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, 1130 &info); 1131 1132 if (!allfamilies) { 1133 if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family) { 1134 p = afp; 1135 (*p->af_status)(s, &info); 1136 } 1137 } else for (p = afs; p->af_name; p++) { 1138 if (p->af_af == info.rti_info[RTAX_IFA]->sa_family) 1139 (*p->af_status)(s, &info); 1140 } 1141 addrcount--; 1142 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); 1143 } 1144 if (allfamilies || afp->af_status == link_status) 1145 link_status(s, (struct rt_addrinfo *)sdl); 1146#ifdef USE_IF_MEDIA 1147 if (allfamilies || afp->af_status == media_status) 1148 media_status(s, NULL); 1149#endif 1150#ifdef USE_VLANS 1151 if (allfamilies || afp->af_status == vlan_status) 1152 vlan_status(s, NULL); 1153#endif 1154#ifdef USE_IEEE80211 1155 if (allfamilies || afp->af_status == ieee80211_status) 1156 ieee80211_status(s, NULL); 1157#endif 1158#ifdef USE_MAC 1159 if (allfamilies || afp->af_status == maclabel_status) 1160 maclabel_status(s, NULL); 1161#endif 1162 strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name); 1163 if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 1164 printf("%s", ifs.ascii); 1165 1166 if (!allfamilies && !p && 1167#ifdef USE_IF_MEDIA 1168 afp->af_status != media_status && 1169#endif 1170 afp->af_status != link_status 1171#ifdef USE_VLANS 1172 && afp->af_status != vlan_status 1173#endif 1174 ) 1175 warnx("%s has no %s interface address!", name, afp->af_name); 1176 1177 close(s); 1178 return; 1179} 1180 1181void 1182tunnel_status(int s) 1183{ 1184 char psrcaddr[NI_MAXHOST]; 1185 char pdstaddr[NI_MAXHOST]; 1186 u_long srccmd, dstcmd; 1187 struct ifreq *ifrp; 1188 const char *ver = ""; 1189#ifdef NI_WITHSCOPEID 1190 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 1191#else 1192 const int niflag = NI_NUMERICHOST; 1193#endif 1194#ifdef INET6 1195 struct in6_ifreq in6_ifr; 1196 int s6; 1197#endif /* INET6 */ 1198 1199 psrcaddr[0] = pdstaddr[0] = '\0'; 1200 1201#ifdef INET6 1202 memset(&in6_ifr, 0, sizeof(in6_ifr)); 1203 strncpy(in6_ifr.ifr_name, name, IFNAMSIZ); 1204 s6 = socket(AF_INET6, SOCK_DGRAM, 0); 1205 if (s6 < 0) { 1206 srccmd = SIOCGIFPSRCADDR; 1207 dstcmd = SIOCGIFPDSTADDR; 1208 ifrp = 𝔦 1209 } else { 1210 close(s6); 1211 srccmd = SIOCGIFPSRCADDR_IN6; 1212 dstcmd = SIOCGIFPDSTADDR_IN6; 1213 ifrp = (struct ifreq *)&in6_ifr; 1214 } 1215#else /* INET6 */ 1216 srccmd = SIOCGIFPSRCADDR; 1217 dstcmd = SIOCGIFPDSTADDR; 1218 ifrp = 𝔦 1219#endif /* INET6 */ 1220 1221 if (ioctl(s, srccmd, (caddr_t)ifrp) < 0) 1222 return; 1223#ifdef INET6 1224 if (ifrp->ifr_addr.sa_family == AF_INET6) 1225 in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr); 1226#endif 1227 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 1228 psrcaddr, sizeof(psrcaddr), 0, 0, niflag); 1229#ifdef INET6 1230 if (ifrp->ifr_addr.sa_family == AF_INET6) 1231 ver = "6"; 1232#endif 1233 1234 if (ioctl(s, dstcmd, (caddr_t)ifrp) < 0) 1235 return; 1236#ifdef INET6 1237 if (ifrp->ifr_addr.sa_family == AF_INET6) 1238 in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr); 1239#endif 1240 getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len, 1241 pdstaddr, sizeof(pdstaddr), 0, 0, niflag); 1242 1243 printf("\ttunnel inet%s %s --> %s\n", ver, 1244 psrcaddr, pdstaddr); 1245} 1246 1247void 1248in_status(int s __unused, struct rt_addrinfo * info) 1249{ 1250 struct sockaddr_in *sin, null_sin; 1251 1252 memset(&null_sin, 0, sizeof(null_sin)); 1253 1254 sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; 1255 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 1256 1257 if (flags & IFF_POINTOPOINT) { 1258 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1259 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1260 if (!sin) 1261 sin = &null_sin; 1262 printf("--> %s ", inet_ntoa(sin->sin_addr)); 1263 } 1264 1265 sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; 1266 if (!sin) 1267 sin = &null_sin; 1268 printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); 1269 1270 if (flags & IFF_BROADCAST) { 1271 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1272 sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; 1273 if (sin && sin->sin_addr.s_addr != 0) 1274 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 1275 } 1276 putchar('\n'); 1277} 1278 1279#ifdef INET6 1280void 1281in6_fillscopeid(struct sockaddr_in6 *sin6) 1282{ 1283#if defined(__KAME__) && defined(KAME_SCOPEID) 1284 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1285 sin6->sin6_scope_id = 1286 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 1287 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 1288 } 1289#endif 1290} 1291 1292void 1293in6_status(int s __unused, struct rt_addrinfo * info) 1294{ 1295 struct sockaddr_in6 *sin, null_sin; 1296 struct in6_ifreq ifr6; 1297 int s6; 1298 u_int32_t flags6; 1299 struct in6_addrlifetime lifetime; 1300 time_t t = time(NULL); 1301 int error; 1302 u_int32_t scopeid; 1303 1304 memset(&null_sin, 0, sizeof(null_sin)); 1305 1306 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA]; 1307 strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); 1308 if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 1309 perror("ifconfig: socket"); 1310 return; 1311 } 1312 ifr6.ifr_addr = *sin; 1313 if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) { 1314 perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)"); 1315 close(s6); 1316 return; 1317 } 1318 flags6 = ifr6.ifr_ifru.ifru_flags6; 1319 memset(&lifetime, 0, sizeof(lifetime)); 1320 ifr6.ifr_addr = *sin; 1321 if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) { 1322 perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)"); 1323 close(s6); 1324 return; 1325 } 1326 lifetime = ifr6.ifr_ifru.ifru_lifetime; 1327 close(s6); 1328 1329 /* XXX: embedded link local addr check */ 1330 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1331 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1332 u_short index; 1333 1334 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1335 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1336 if (sin->sin6_scope_id == 0) 1337 sin->sin6_scope_id = ntohs(index); 1338 } 1339 scopeid = sin->sin6_scope_id; 1340 1341 error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, 1342 sizeof(addr_buf), NULL, 0, 1343 NI_NUMERICHOST|NI_WITHSCOPEID); 1344 if (error != 0) 1345 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1346 sizeof(addr_buf)); 1347 printf("\tinet6 %s ", addr_buf); 1348 1349 if (flags & IFF_POINTOPOINT) { 1350 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1351 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_BRD]; 1352 /* 1353 * some of the interfaces do not have valid destination 1354 * address. 1355 */ 1356 if (sin && sin->sin6_family == AF_INET6) { 1357 int error; 1358 1359 /* XXX: embedded link local addr check */ 1360 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && 1361 *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { 1362 u_short index; 1363 1364 index = *(u_short *)&sin->sin6_addr.s6_addr[2]; 1365 *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; 1366 if (sin->sin6_scope_id == 0) 1367 sin->sin6_scope_id = ntohs(index); 1368 } 1369 1370 error = getnameinfo((struct sockaddr *)sin, 1371 sin->sin6_len, addr_buf, 1372 sizeof(addr_buf), NULL, 0, 1373 NI_NUMERICHOST|NI_WITHSCOPEID); 1374 if (error != 0) 1375 inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, 1376 sizeof(addr_buf)); 1377 printf("--> %s ", addr_buf); 1378 } 1379 } 1380 1381 sin = (struct sockaddr_in6 *)info->rti_info[RTAX_NETMASK]; 1382 if (!sin) 1383 sin = &null_sin; 1384 printf("prefixlen %d ", prefix(&sin->sin6_addr, 1385 sizeof(struct in6_addr))); 1386 1387 if ((flags6 & IN6_IFF_ANYCAST) != 0) 1388 printf("anycast "); 1389 if ((flags6 & IN6_IFF_TENTATIVE) != 0) 1390 printf("tentative "); 1391 if ((flags6 & IN6_IFF_DUPLICATED) != 0) 1392 printf("duplicated "); 1393 if ((flags6 & IN6_IFF_DETACHED) != 0) 1394 printf("detached "); 1395 if ((flags6 & IN6_IFF_DEPRECATED) != 0) 1396 printf("deprecated "); 1397 if ((flags6 & IN6_IFF_AUTOCONF) != 0) 1398 printf("autoconf "); 1399 if ((flags6 & IN6_IFF_TEMPORARY) != 0) 1400 printf("temporary "); 1401 1402 if (scopeid) 1403 printf("scopeid 0x%x ", scopeid); 1404 1405 if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { 1406 printf("pltime "); 1407 if (lifetime.ia6t_preferred) { 1408 printf("%s ", lifetime.ia6t_preferred < t 1409 ? "0" : sec2str(lifetime.ia6t_preferred - t)); 1410 } else 1411 printf("infty "); 1412 1413 printf("vltime "); 1414 if (lifetime.ia6t_expire) { 1415 printf("%s ", lifetime.ia6t_expire < t 1416 ? "0" : sec2str(lifetime.ia6t_expire - t)); 1417 } else 1418 printf("infty "); 1419 } 1420 1421 putchar('\n'); 1422} 1423#endif /*INET6*/ 1424 1425#ifndef NO_IPX 1426void 1427ipx_status(int s __unused, struct rt_addrinfo * info) 1428{ 1429 struct sockaddr_ipx *sipx, null_sipx; 1430 1431 memset(&null_sipx, 0, sizeof(null_sipx)); 1432 1433 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_IFA]; 1434 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 1435 1436 if (flags & IFF_POINTOPOINT) { 1437 sipx = (struct sockaddr_ipx *)info->rti_info[RTAX_BRD]; 1438 if (!sipx) 1439 sipx = &null_sipx; 1440 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 1441 } 1442 putchar('\n'); 1443} 1444#endif 1445 1446void 1447at_status(int s __unused, struct rt_addrinfo * info) 1448{ 1449 struct sockaddr_at *sat, null_sat; 1450 struct netrange *nr; 1451 1452 memset(&null_sat, 0, sizeof(null_sat)); 1453 1454 sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA]; 1455 nr = &sat->sat_range.r_netrange; 1456 printf("\tatalk %d.%d range %d-%d phase %d", 1457 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1458 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 1459 if (flags & IFF_POINTOPOINT) { 1460 /* note RTAX_BRD overlap with IFF_BROADCAST */ 1461 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1462 if (!sat) 1463 sat = &null_sat; 1464 printf("--> %d.%d", 1465 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 1466 } 1467 if (flags & IFF_BROADCAST) { 1468 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1469 sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD]; 1470 if (sat) 1471 printf(" broadcast %d.%d", 1472 ntohs(sat->sat_addr.s_net), 1473 sat->sat_addr.s_node); 1474 } 1475 1476 putchar('\n'); 1477} 1478 1479void 1480link_status(int s __unused, struct rt_addrinfo *info) 1481{ 1482 struct sockaddr_dl *sdl = (struct sockaddr_dl *)info; 1483 1484 if (sdl->sdl_alen > 0) { 1485 if (sdl->sdl_type == IFT_ETHER && 1486 sdl->sdl_alen == ETHER_ADDR_LEN) 1487 printf("\tether %s\n", 1488 ether_ntoa((struct ether_addr *)LLADDR(sdl))); 1489 else { 1490 int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0; 1491 1492 printf("\tlladdr %s\n", link_ntoa(sdl) + n); 1493 } 1494 } 1495} 1496 1497void 1498Perror(const char *cmd) 1499{ 1500 switch (errno) { 1501 1502 case ENXIO: 1503 errx(1, "%s: no such interface", cmd); 1504 break; 1505 1506 case EPERM: 1507 errx(1, "%s: permission denied", cmd); 1508 break; 1509 1510 default: 1511 err(1, "%s", cmd); 1512 } 1513} 1514 1515#define SIN(x) ((struct sockaddr_in *) &(x)) 1516struct sockaddr_in *sintab[] = { 1517SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1518SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1519 1520void 1521in_getaddr(const char *s, int which) 1522{ 1523 struct sockaddr_in *sin = sintab[which]; 1524 struct hostent *hp; 1525 struct netent *np; 1526 1527 sin->sin_len = sizeof(*sin); 1528 if (which != MASK) 1529 sin->sin_family = AF_INET; 1530 1531 if (which == ADDR) { 1532 char *p = NULL; 1533 1534 if((p = strrchr(s, '/')) != NULL) { 1535 /* address is `name/masklen' */ 1536 int masklen; 1537 int ret; 1538 struct sockaddr_in *min = sintab[MASK]; 1539 *p = '\0'; 1540 ret = sscanf(p+1, "%u", &masklen); 1541 if(ret != 1 || (masklen < 0 || masklen > 32)) { 1542 *p = '/'; 1543 errx(1, "%s: bad value", s); 1544 } 1545 min->sin_len = sizeof(*min); 1546 min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) & 1547 0xffffffff); 1548 } 1549 } 1550 1551 if (inet_aton(s, &sin->sin_addr)) 1552 return; 1553 if ((hp = gethostbyname(s)) != 0) 1554 bcopy(hp->h_addr, (char *)&sin->sin_addr, 1555 MIN(hp->h_length, sizeof(sin->sin_addr))); 1556 else if ((np = getnetbyname(s)) != 0) 1557 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1558 else 1559 errx(1, "%s: bad value", s); 1560} 1561 1562#ifdef INET6 1563#define SIN6(x) ((struct sockaddr_in6 *) &(x)) 1564struct sockaddr_in6 *sin6tab[] = { 1565SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 1566SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 1567 1568void 1569in6_getaddr(const char *s, int which) 1570{ 1571 struct sockaddr_in6 *sin = sin6tab[which]; 1572 struct addrinfo hints, *res; 1573 int error = -1; 1574 1575 newaddr &= 1; 1576 1577 sin->sin6_len = sizeof(*sin); 1578 if (which != MASK) 1579 sin->sin6_family = AF_INET6; 1580 1581 if (which == ADDR) { 1582 char *p = NULL; 1583 if((p = strrchr(s, '/')) != NULL) { 1584 *p = '\0'; 1585 in6_getprefix(p + 1, MASK); 1586 explicit_prefix = 1; 1587 } 1588 } 1589 1590 if (sin->sin6_family == AF_INET6) { 1591 bzero(&hints, sizeof(struct addrinfo)); 1592 hints.ai_family = AF_INET6; 1593 error = getaddrinfo(s, NULL, &hints, &res); 1594 } 1595 if (error != 0) { 1596 if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) 1597 errx(1, "%s: bad value", s); 1598 } else 1599 bcopy(res->ai_addr, sin, res->ai_addrlen); 1600} 1601 1602void 1603in6_getprefix(const char *plen, int which) 1604{ 1605 struct sockaddr_in6 *sin = sin6tab[which]; 1606 u_char *cp; 1607 int len = atoi(plen); 1608 1609 if ((len < 0) || (len > 128)) 1610 errx(1, "%s: bad value", plen); 1611 sin->sin6_len = sizeof(*sin); 1612 if (which != MASK) 1613 sin->sin6_family = AF_INET6; 1614 if ((len == 0) || (len == 128)) { 1615 memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); 1616 return; 1617 } 1618 memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); 1619 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 1620 *cp++ = 0xff; 1621 *cp = 0xff << (8 - len); 1622} 1623#endif 1624 1625/* 1626 * Print a value a la the %b format of the kernel's printf 1627 */ 1628void 1629printb(const char *s, unsigned v, const char *bits) 1630{ 1631 int i, any = 0; 1632 char c; 1633 1634 if (bits && *bits == 8) 1635 printf("%s=%o", s, v); 1636 else 1637 printf("%s=%x", s, v); 1638 bits++; 1639 if (bits) { 1640 putchar('<'); 1641 while ((i = *bits++) != '\0') { 1642 if (v & (1 << (i-1))) { 1643 if (any) 1644 putchar(','); 1645 any = 1; 1646 for (; (c = *bits) > 32; bits++) 1647 putchar(c); 1648 } else 1649 for (; *bits > 32; bits++) 1650 ; 1651 } 1652 putchar('>'); 1653 } 1654} 1655 1656#ifndef NO_IPX 1657#define SIPX(x) ((struct sockaddr_ipx *) &(x)) 1658struct sockaddr_ipx *sipxtab[] = { 1659SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 1660SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 1661 1662void 1663ipx_getaddr(const char *addr, int which) 1664{ 1665 struct sockaddr_ipx *sipx = sipxtab[which]; 1666 1667 sipx->sipx_family = AF_IPX; 1668 sipx->sipx_len = sizeof(*sipx); 1669 sipx->sipx_addr = ipx_addr(addr); 1670 if (which == MASK) 1671 printf("Attempt to set IPX netmask will be ineffectual\n"); 1672} 1673#endif 1674 1675void 1676at_getaddr(const char *addr, int which) 1677{ 1678 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 1679 u_int net, node; 1680 1681 sat->sat_family = AF_APPLETALK; 1682 sat->sat_len = sizeof(*sat); 1683 if (which == MASK) 1684 errx(1, "AppleTalk does not use netmasks"); 1685 if (sscanf(addr, "%u.%u", &net, &node) != 2 1686 || net > 0xffff || node > 0xfe) 1687 errx(1, "%s: illegal address", addr); 1688 sat->sat_addr.s_net = htons(net); 1689 sat->sat_addr.s_node = node; 1690} 1691 1692void 1693link_getaddr(const char *addr, int which) 1694{ 1695 char *temp; 1696 struct sockaddr_dl sdl; 1697 struct sockaddr *sa = &ridreq.ifr_addr; 1698 1699 if (which != ADDR) 1700 errx(1, "can't set link-level netmask or broadcast"); 1701 if ((temp = malloc(strlen(addr) + 1)) == NULL) 1702 errx(1, "malloc failed"); 1703 temp[0] = ':'; 1704 strcpy(temp + 1, addr); 1705 sdl.sdl_len = sizeof(sdl); 1706 link_addr(temp, &sdl); 1707 free(temp); 1708 if (sdl.sdl_alen > sizeof(sa->sa_data)) 1709 errx(1, "malformed link-level address"); 1710 sa->sa_family = AF_LINK; 1711 sa->sa_len = sdl.sdl_alen; 1712 bcopy(LLADDR(&sdl), sa->sa_data, sdl.sdl_alen); 1713} 1714 1715/* XXX FIXME -- should use strtoul for better parsing. */ 1716void 1717setatrange(const char *range, int dummy __unused, int s, 1718 const struct afswtch *afp) 1719{ 1720 u_int first = 123, last = 123; 1721 1722 if (sscanf(range, "%u-%u", &first, &last) != 2 1723 || first == 0 || first > 0xffff 1724 || last == 0 || last > 0xffff || first > last) 1725 errx(1, "%s: illegal net range: %u-%u", range, first, last); 1726 at_nr.nr_firstnet = htons(first); 1727 at_nr.nr_lastnet = htons(last); 1728} 1729 1730void 1731setatphase(const char *phase, int dummy __unused, int s, 1732 const struct afswtch *afp) 1733{ 1734 if (!strcmp(phase, "1")) 1735 at_nr.nr_phase = 1; 1736 else if (!strcmp(phase, "2")) 1737 at_nr.nr_phase = 2; 1738 else 1739 errx(1, "%s: illegal phase", phase); 1740} 1741 1742void 1743checkatrange(struct sockaddr_at *sat) 1744{ 1745 if (at_nr.nr_phase == 0) 1746 at_nr.nr_phase = 2; /* Default phase 2 */ 1747 if (at_nr.nr_firstnet == 0) 1748 at_nr.nr_firstnet = /* Default range of one */ 1749 at_nr.nr_lastnet = sat->sat_addr.s_net; 1750printf("\tatalk %d.%d range %d-%d phase %d\n", 1751 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1752 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 1753 if ((u_short) ntohs(at_nr.nr_firstnet) > 1754 (u_short) ntohs(sat->sat_addr.s_net) 1755 || (u_short) ntohs(at_nr.nr_lastnet) < 1756 (u_short) ntohs(sat->sat_addr.s_net)) 1757 errx(1, "AppleTalk address is not in range"); 1758 sat->sat_range.r_netrange = at_nr; 1759} 1760 1761#ifdef INET6 1762int 1763prefix(void *val, int size) 1764{ 1765 u_char *name = (u_char *)val; 1766 int byte, bit, plen = 0; 1767 1768 for (byte = 0; byte < size; byte++, plen += 8) 1769 if (name[byte] != 0xff) 1770 break; 1771 if (byte == size) 1772 return (plen); 1773 for (bit = 7; bit != 0; bit--, plen++) 1774 if (!(name[byte] & (1 << bit))) 1775 break; 1776 for (; bit != 0; bit--) 1777 if (name[byte] & (1 << bit)) 1778 return(0); 1779 byte++; 1780 for (; byte < size; byte++) 1781 if (name[byte]) 1782 return(0); 1783 return (plen); 1784} 1785 1786static char * 1787sec2str(time_t total) 1788{ 1789 static char result[256]; 1790 int days, hours, mins, secs; 1791 int first = 1; 1792 char *p = result; 1793 1794 if (0) { 1795 days = total / 3600 / 24; 1796 hours = (total / 3600) % 24; 1797 mins = (total / 60) % 60; 1798 secs = total % 60; 1799 1800 if (days) { 1801 first = 0; 1802 p += sprintf(p, "%dd", days); 1803 } 1804 if (!first || hours) { 1805 first = 0; 1806 p += sprintf(p, "%dh", hours); 1807 } 1808 if (!first || mins) { 1809 first = 0; 1810 p += sprintf(p, "%dm", mins); 1811 } 1812 sprintf(p, "%ds", secs); 1813 } else 1814 sprintf(result, "%lu", (unsigned long)total); 1815 1816 return(result); 1817} 1818#endif /*INET6*/ 1819 1820void 1821ifmaybeload(char *name) 1822{ 1823 struct module_stat mstat; 1824 int fileid, modid; 1825 char ifkind[35], *cp, *dp; 1826 1827 /* turn interface and unit into module name */ 1828 strcpy(ifkind, "if_"); 1829 for (cp = name, dp = ifkind + 3; 1830 (*cp != 0) && !isdigit(*cp); cp++, dp++) 1831 *dp = *cp; 1832 *dp = 0; 1833 1834 /* scan files in kernel */ 1835 mstat.version = sizeof(struct module_stat); 1836 for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1837 /* scan modules in file */ 1838 for (modid = kldfirstmod(fileid); modid > 0; 1839 modid = modfnext(modid)) { 1840 if (modstat(modid, &mstat) < 0) 1841 continue; 1842 /* strip bus name if present */ 1843 if ((cp = strchr(mstat.name, '/')) != NULL) { 1844 cp++; 1845 } else { 1846 cp = mstat.name; 1847 } 1848 /* already loaded? */ 1849 if (strncmp(name, cp, strlen(cp)) == 0 || 1850 strncmp(ifkind, cp, strlen(cp)) == 0) 1851 return; 1852 } 1853 } 1854 1855 /* not present, we should try to load it */ 1856 kldload(ifkind); 1857} 1858 1859void 1860list_cloners(void) 1861{ 1862 struct if_clonereq ifcr; 1863 char *cp, *buf; 1864 int idx; 1865 int s; 1866 1867 s = socket(AF_INET, SOCK_DGRAM, 0); 1868 if (s == -1) 1869 err(1, "socket"); 1870 1871 memset(&ifcr, 0, sizeof(ifcr)); 1872 1873 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 1874 err(1, "SIOCIFGCLONERS for count"); 1875 1876 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 1877 if (buf == NULL) 1878 err(1, "unable to allocate cloner name buffer"); 1879 1880 ifcr.ifcr_count = ifcr.ifcr_total; 1881 ifcr.ifcr_buffer = buf; 1882 1883 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 1884 err(1, "SIOCIFGCLONERS for names"); 1885 1886 /* 1887 * In case some disappeared in the mean time, clamp it down. 1888 */ 1889 if (ifcr.ifcr_count > ifcr.ifcr_total) 1890 ifcr.ifcr_count = ifcr.ifcr_total; 1891 1892 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 1893 if (idx > 0) 1894 putchar(' '); 1895 printf("%s", cp); 1896 } 1897 1898 putchar('\n'); 1899 free(buf); 1900} 1901 1902void 1903clone_create(void) 1904{ 1905 int s; 1906 1907 s = socket(AF_INET, SOCK_DGRAM, 0); 1908 if (s == -1) 1909 err(1, "socket"); 1910 1911 memset(&ifr, 0, sizeof(ifr)); 1912 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1913 if (ioctl(s, SIOCIFCREATE, &ifr) < 0) 1914 err(1, "SIOCIFCREATE"); 1915 1916 /* 1917 * If we get a different name back then we put in, we probably 1918 * want to print it out, but we might change our mind later so 1919 * we just signal our intrest and leave the printout for later. 1920 */ 1921 if (strcmp(name, ifr.ifr_name) != 0) { 1922 printname = 1; 1923 strlcpy(name, ifr.ifr_name, sizeof(name)); 1924 } 1925 1926 close(s); 1927} 1928 1929void 1930clone_destroy(const char *val, int d, int s, const struct afswtch *rafp) 1931{ 1932 1933 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1934 if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) 1935 err(1, "SIOCIFDESTROY"); 1936 /* 1937 * If we create and destroy an interface in the same command, 1938 * there isn't any reason to print it's name. 1939 */ 1940 printname = 0; 1941} 1942