ifconfig.c revision 1.161
1/* $NetBSD: ifconfig.c,v 1.161 2005/03/19 23:32:55 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40/* 41 * Copyright (c) 1983, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. Neither the name of the University nor the names of its contributors 53 * may be used to endorse or promote products derived from this software 54 * without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66 * SUCH DAMAGE. 67 */ 68 69#include <sys/cdefs.h> 70#ifndef lint 71__COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\ 72 The Regents of the University of California. All rights reserved.\n"); 73#endif /* not lint */ 74 75#ifndef lint 76#if 0 77static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 78#else 79__RCSID("$NetBSD: ifconfig.c,v 1.161 2005/03/19 23:32:55 thorpej Exp $"); 80#endif 81#endif /* not lint */ 82 83#include <sys/param.h> 84#include <sys/socket.h> 85#include <sys/ioctl.h> 86 87#include <net/if.h> 88#include <net/if_dl.h> 89#include <net/if_media.h> 90#include <net/if_ether.h> 91#include <netinet/in.h> 92#include <netinet/in_var.h> 93#ifdef INET6 94#include <netinet6/nd6.h> 95#endif 96#include <arpa/inet.h> 97 98#define NSIP 99#include <netns/ns.h> 100#include <netns/ns_if.h> 101#include <netdb.h> 102 103#define EON 104#include <netiso/iso.h> 105#include <netiso/iso_var.h> 106#include <sys/protosw.h> 107 108#include <ctype.h> 109#include <err.h> 110#include <errno.h> 111#include <stddef.h> 112#include <stdio.h> 113#include <stdlib.h> 114#include <string.h> 115#include <unistd.h> 116#include <ifaddrs.h> 117#include <util.h> 118 119#include "extern.h" 120 121#ifndef INET_ONLY 122#include "af_atalk.h" 123#endif /* ! INET_ONLY */ 124 125#include "agr.h" 126#include "ieee80211.h" 127#include "tunnel.h" 128#include "vlan.h" 129 130struct ifreq ifr, ridreq; 131struct ifaliasreq addreq __attribute__((aligned(4))); 132struct in_aliasreq in_addreq; 133#ifdef INET6 134struct in6_ifreq ifr6; 135struct in6_ifreq in6_ridreq; 136struct in6_aliasreq in6_addreq; 137#endif 138struct iso_ifreq iso_ridreq; 139struct iso_aliasreq iso_addreq; 140struct sockaddr_in netmask; 141 142char name[30]; 143u_short flags; 144int setaddr, setipdst, doalias; 145u_long metric, mtu; 146int clearaddr, s; 147int newaddr = -1; 148int conflicting = 0; 149int nsellength = 1; 150int af; 151int aflag, bflag, Cflag, dflag, lflag, mflag, sflag, uflag, vflag, zflag; 152#ifdef INET6 153int Lflag; 154#endif 155int explicit_prefix = 0; 156 157struct ifcapreq g_ifcr; 158int g_ifcr_updated; 159 160void notealias(const char *, int); 161void notrailers(const char *, int); 162void setifaddr(const char *, int); 163void setifdstaddr(const char *, int); 164void setifflags(const char *, int); 165void setifcaps(const char *, int); 166void setifbroadaddr(const char *, int); 167void setifipdst(const char *, int); 168void setifmetric(const char *, int); 169void setifmtu(const char *, int); 170void setifnetmask(const char *, int); 171void setifprefixlen(const char *, int); 172void setnsellength(const char *, int); 173void setsnpaoffset(const char *, int); 174#ifdef INET6 175void setia6flags(const char *, int); 176void setia6pltime(const char *, int); 177void setia6vltime(const char *, int); 178void setia6lifetime(const char *, const char *); 179void setia6eui64(const char *, int); 180#endif 181void setmedia(const char *, int); 182void setmediamode(const char *, int); 183void setmediaopt(const char *, int); 184void unsetmediaopt(const char *, int); 185void setmediainst(const char *, int); 186void clone_create(const char *, int); 187void clone_destroy(const char *, int); 188void fixnsel(struct sockaddr_iso *); 189int main(int, char *[]); 190 191/* 192 * Media stuff. Whenever a media command is first performed, the 193 * currently select media is grabbed for this interface. If `media' 194 * is given, the current media word is modifed. `mediaopt' commands 195 * only modify the set and clear words. They then operate on the 196 * current media word later. 197 */ 198int media_current; 199int mediaopt_set; 200int mediaopt_clear; 201 202int actions; /* Actions performed */ 203 204#define A_MEDIA 0x0001 /* media command */ 205#define A_MEDIAOPTSET 0x0002 /* mediaopt command */ 206#define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */ 207#define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR) 208#define A_MEDIAINST 0x0008 /* instance or inst command */ 209#define A_MEDIAMODE 0x0010 /* mode command */ 210 211#define NEXTARG 0xffffff 212#define NEXTARG2 0xfffffe 213 214const struct cmd { 215 const char *c_name; 216 int c_parameter; /* NEXTARG means next argv */ 217 int c_action; /* defered action */ 218 void (*c_func)(const char *, int); 219 void (*c_func2)(const char *, const char *); 220} cmds[] = { 221 { "up", IFF_UP, 0, setifflags } , 222 { "down", -IFF_UP, 0, setifflags }, 223 { "trailers", -1, 0, notrailers }, 224 { "-trailers", 1, 0, notrailers }, 225 { "arp", -IFF_NOARP, 0, setifflags }, 226 { "-arp", IFF_NOARP, 0, setifflags }, 227 { "debug", IFF_DEBUG, 0, setifflags }, 228 { "-debug", -IFF_DEBUG, 0, setifflags }, 229 { "alias", IFF_UP, 0, notealias }, 230 { "-alias", -IFF_UP, 0, notealias }, 231 { "delete", -IFF_UP, 0, notealias }, 232#ifdef notdef 233#define EN_SWABIPS 0x1000 234 { "swabips", EN_SWABIPS, 0, setifflags }, 235 { "-swabips", -EN_SWABIPS, 0, setifflags }, 236#endif 237 { "netmask", NEXTARG, 0, setifnetmask }, 238 { "metric", NEXTARG, 0, setifmetric }, 239 { "mtu", NEXTARG, 0, setifmtu }, 240 { "bssid", NEXTARG, 0, setifbssid }, 241 { "-bssid", -1, 0, setifbssid }, 242 { "chan", NEXTARG, 0, setifchan }, 243 { "-chan", -1, 0, setifchan }, 244 { "ssid", NEXTARG, 0, setifnwid }, 245 { "nwid", NEXTARG, 0, setifnwid }, 246 { "nwkey", NEXTARG, 0, setifnwkey }, 247 { "-nwkey", -1, 0, setifnwkey }, 248 { "powersave", 1, 0, setifpowersave }, 249 { "-powersave", 0, 0, setifpowersave }, 250 { "powersavesleep", NEXTARG, 0, setifpowersavesleep }, 251 { "broadcast", NEXTARG, 0, setifbroadaddr }, 252 { "ipdst", NEXTARG, 0, setifipdst }, 253 { "prefixlen", NEXTARG, 0, setifprefixlen}, 254#ifdef INET6 255 { "anycast", IN6_IFF_ANYCAST, 0, setia6flags }, 256 { "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags }, 257 { "tentative", IN6_IFF_TENTATIVE, 0, setia6flags }, 258 { "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags }, 259 { "deprecated", IN6_IFF_DEPRECATED, 0, setia6flags }, 260 { "-deprecated", -IN6_IFF_DEPRECATED, 0, setia6flags }, 261 { "pltime", NEXTARG, 0, setia6pltime }, 262 { "vltime", NEXTARG, 0, setia6vltime }, 263 { "eui64", 0, 0, setia6eui64 }, 264#endif /*INET6*/ 265#ifndef INET_ONLY 266 { "range", NEXTARG, 0, setatrange }, 267 { "phase", NEXTARG, 0, setatphase }, 268 { "snpaoffset", NEXTARG, 0, setsnpaoffset }, 269 { "nsellength", NEXTARG, 0, setnsellength }, 270#endif /* INET_ONLY */ 271 { "tunnel", NEXTARG2, 0, NULL, 272 settunnel } , 273 { "deletetunnel", 0, 0, deletetunnel }, 274 { "vlan", NEXTARG, 0, setvlan } , 275 { "vlanif", NEXTARG, 0, setvlanif } , 276 { "-vlanif", 0, 0, unsetvlanif } , 277#if 0 278 /* XXX `create' special-cased below */ 279 { "create", 0, 0, clone_create } , 280#endif 281 { "destroy", 0, 0, clone_destroy } , 282 { "link0", IFF_LINK0, 0, setifflags } , 283 { "-link0", -IFF_LINK0, 0, setifflags } , 284 { "link1", IFF_LINK1, 0, setifflags } , 285 { "-link1", -IFF_LINK1, 0, setifflags } , 286 { "link2", IFF_LINK2, 0, setifflags } , 287 { "-link2", -IFF_LINK2, 0, setifflags } , 288 { "media", NEXTARG, A_MEDIA, setmedia }, 289 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt }, 290 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt }, 291 { "mode", NEXTARG, A_MEDIAMODE, setmediamode }, 292 { "instance", NEXTARG, A_MEDIAINST, setmediainst }, 293 { "inst", NEXTARG, A_MEDIAINST, setmediainst }, 294 { "ip4csum", IFCAP_CSUM_IPv4,0, setifcaps }, 295 { "-ip4csum", -IFCAP_CSUM_IPv4,0, setifcaps }, 296 { "tcp4csum", IFCAP_CSUM_TCPv4,0, setifcaps }, 297 { "-tcp4csum", -IFCAP_CSUM_TCPv4,0, setifcaps }, 298 { "udp4csum", IFCAP_CSUM_UDPv4,0, setifcaps }, 299 { "-udp4csum", -IFCAP_CSUM_UDPv4,0, setifcaps }, 300 { "tcp6csum", IFCAP_CSUM_TCPv6,0, setifcaps }, 301 { "-tcp6csum", -IFCAP_CSUM_TCPv6,0, setifcaps }, 302 { "udp6csum", IFCAP_CSUM_UDPv6,0, setifcaps }, 303 { "-udp6csum", -IFCAP_CSUM_UDPv6,0, setifcaps }, 304 { "tcp4csum-rx",IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 305 { "-tcp4csum-rx",-IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 306 { "udp4csum-rx",IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 307 { "-udp4csum-rx",-IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 308 { "tso4", IFCAP_TSOv4, 0, setifcaps }, 309 { "-tso4", -IFCAP_TSOv4, 0, setifcaps }, 310 { "agrport", NEXTARG, 0, agraddport } , 311 { "-agrport", NEXTARG, 0, agrremport } , 312 { 0, 0, 0, setifaddr }, 313 { 0, 0, 0, setifdstaddr }, 314}; 315 316void adjust_nsellength(void); 317int getinfo(struct ifreq *); 318int carrier(void); 319void printall(const char *); 320void list_cloners(void); 321int prefix(void *, int); 322void status(const struct sockaddr_dl *); 323void usage(void); 324char *sec2str(time_t); 325 326void print_media_word(int, const char *); 327void process_media_commands(void); 328void init_current_media(void); 329 330/* 331 * XNS support liberally adapted from code written at the University of 332 * Maryland principally by James O'Toole and Chris Torek. 333 */ 334void in_alias(struct ifreq *); 335void in_status(int); 336void in_getaddr(const char *, int); 337void in_getprefix(const char *, int); 338#ifdef INET6 339void in6_fillscopeid(struct sockaddr_in6 *sin6); 340void in6_alias(struct in6_ifreq *); 341void in6_status(int); 342void in6_getaddr(const char *, int); 343void in6_getprefix(const char *, int); 344#endif 345void xns_status(int); 346void xns_getaddr(const char *, int); 347void iso_status(int); 348void iso_getaddr(const char *, int); 349 350/* Known address families */ 351const struct afswtch afs[] = { 352 { "inet", AF_INET, in_status, in_getaddr, in_getprefix, 353 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &ridreq, &in_addreq }, 354#ifdef INET6 355 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 356 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 357 /* 358 * Deleting the first address before setting new one is 359 * not prefered way in this protocol. 360 */ 361 0, 362 &in6_ridreq, &in6_addreq }, 363#endif 364#ifndef INET_ONLY /* small version, for boot media */ 365 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 366 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &addreq, &addreq }, 367 { "ns", AF_NS, xns_status, xns_getaddr, NULL, 368 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, &ridreq, &addreq }, 369 { "iso", AF_ISO, iso_status, iso_getaddr, NULL, 370 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, SIOCGIFADDR_ISO, 371 &iso_ridreq, &iso_addreq }, 372#endif /* INET_ONLY */ 373 { 0, 0, 0, 0 } 374}; 375 376const struct afswtch *afp; /*the address family being set or asked about*/ 377 378int 379main(int argc, char *argv[]) 380{ 381 int ch; 382 383 /* Parse command-line options */ 384 aflag = mflag = vflag = zflag = 0; 385 while ((ch = getopt(argc, argv, "AabCdlmsuvz" 386#ifdef INET6 387 "L" 388#endif 389 )) != -1) { 390 switch (ch) { 391 case 'A': 392 warnx("-A is deprecated"); 393 break; 394 395 case 'a': 396 aflag = 1; 397 break; 398 399 case 'b': 400 bflag = 1; 401 break; 402 403 case 'C': 404 Cflag = 1; 405 break; 406 407 case 'd': 408 dflag = 1; 409 break; 410 411#ifdef INET6 412 case 'L': 413 Lflag = 1; 414 break; 415#endif 416 417 case 'l': 418 lflag = 1; 419 break; 420 421 case 'm': 422 mflag = 1; 423 break; 424 425 case 's': 426 sflag = 1; 427 break; 428 429 case 'u': 430 uflag = 1; 431 break; 432 433 case 'v': 434 vflag = 1; 435 break; 436 437 case 'z': 438 zflag = 1; 439 break; 440 441 442 default: 443 usage(); 444 /* NOTREACHED */ 445 } 446 } 447 argc -= optind; 448 argv += optind; 449 450 /* 451 * -l means "list all interfaces", and is mutally exclusive with 452 * all other flags/commands. 453 * 454 * -C means "list all names of cloners", and it mutually exclusive 455 * with all other flags/commands. 456 * 457 * -a means "print status of all interfaces". 458 */ 459 if ((lflag || Cflag) && (aflag || mflag || vflag || argc || zflag)) 460 usage(); 461#ifdef INET6 462 if ((lflag || Cflag) && Lflag) 463 usage(); 464#endif 465 if (lflag && Cflag) 466 usage(); 467 if (Cflag) { 468 if (argc) 469 usage(); 470 list_cloners(); 471 exit(0); 472 } 473 if (aflag || lflag) { 474 if (argc > 1) 475 usage(); 476 else if (argc == 1) { 477 afp = lookup_af_byname(argv[0]); 478 if (afp == NULL) 479 usage(); 480 } 481 if (afp) 482 af = ifr.ifr_addr.sa_family = afp->af_af; 483 else 484 af = ifr.ifr_addr.sa_family = afs[0].af_af; 485 printall(NULL); 486 exit(0); 487 } 488 489 /* Make sure there's an interface name. */ 490 if (argc < 1) 491 usage(); 492 if (strlcpy(name, argv[0], sizeof(name)) >= sizeof(name)) 493 errx(1, "interface name '%s' too long", argv[0]); 494 argc--; argv++; 495 496 /* 497 * NOTE: We must special-case the `create' command right 498 * here as we would otherwise fail in getinfo(). 499 */ 500 if (argc > 0 && strcmp(argv[0], "create") == 0) { 501 clone_create(argv[0], 0); 502 argc--, argv++; 503 if (argc == 0) 504 exit(0); 505 } 506 507 /* Check for address family. */ 508 afp = NULL; 509 if (argc > 0) { 510 afp = lookup_af_byname(argv[0]); 511 if (afp != NULL) { 512 argv++; 513 argc--; 514 } 515 } 516 517 /* Initialize af, just for use in getinfo(). */ 518 if (afp == NULL) 519 af = afs->af_af; 520 else 521 af = afp->af_af; 522 523 /* Get information about the interface. */ 524 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 525 if (getinfo(&ifr) < 0) 526 exit(1); 527 528 if (sflag) { 529 if (argc != 0) 530 usage(); 531 else 532 exit(carrier()); 533 } 534 535 /* No more arguments means interface status. */ 536 if (argc == 0) { 537 printall(name); 538 exit(0); 539 } 540 541 /* The following operations assume inet family as the default. */ 542 if (afp == NULL) 543 afp = afs; 544 af = ifr.ifr_addr.sa_family = afp->af_af; 545 546#ifdef INET6 547 /* initialization */ 548 in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 549 in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 550#endif 551 552 /* Process commands. */ 553 while (argc > 0) { 554 const struct cmd *p; 555 556 for (p = cmds; p->c_name; p++) 557 if (strcmp(argv[0], p->c_name) == 0) 558 break; 559 if (p->c_name == 0 && setaddr) { 560 if ((flags & IFF_POINTOPOINT) == 0) { 561 errx(EXIT_FAILURE, 562 "can't set destination address %s", 563 "on non-point-to-point link"); 564 } 565 p++; /* got src, do dst */ 566 } 567 if (p->c_func != NULL || p->c_func2 != NULL) { 568 if (p->c_parameter == NEXTARG) { 569 if (argc < 2) 570 errx(EXIT_FAILURE, 571 "'%s' requires argument", 572 p->c_name); 573 (*p->c_func)(argv[1], 0); 574 argc--, argv++; 575 } else if (p->c_parameter == NEXTARG2) { 576 if (argc < 3) 577 errx(EXIT_FAILURE, 578 "'%s' requires 2 arguments", 579 p->c_name); 580 (*p->c_func2)(argv[1], argv[2]); 581 argc -= 2, argv += 2; 582 } else 583 (*p->c_func)(argv[0], p->c_parameter); 584 actions |= p->c_action; 585 } 586 argc--, argv++; 587 } 588 589 /* 590 * See if multiple alias, -alias, or delete commands were 591 * specified. More than one constitutes an invalid command line 592 */ 593 594 if (conflicting > 1) 595 errx(EXIT_FAILURE, 596 "Only one use of alias, -alias or delete is valid."); 597 598 /* Process any media commands that may have been issued. */ 599 process_media_commands(); 600 601 if (af == AF_INET6 && explicit_prefix == 0) { 602 /* 603 * Aggregatable address architecture defines all prefixes 604 * are 64. So, it is convenient to set prefixlen to 64 if 605 * it is not specified. 606 */ 607 setifprefixlen("64", 0); 608 /* in6_getprefix("64", MASK) if MASK is available here... */ 609 } 610 611#ifndef INET_ONLY 612 if (af == AF_ISO) 613 adjust_nsellength(); 614 615 if (af == AF_APPLETALK) 616 checkatrange(&addreq.ifra_addr); 617 618 if (setipdst && af==AF_NS) { 619 struct nsip_req rq; 620 int size = sizeof(rq); 621 622 rq.rq_ns = addreq.ifra_addr; 623 rq.rq_ip = addreq.ifra_dstaddr; 624 625 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 626 warn("encapsulation routing"); 627 } 628 629#endif /* INET_ONLY */ 630 631 if (clearaddr) { 632 (void) strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 633 if (ioctl(s, afp->af_difaddr, afp->af_ridreq) == -1) 634 err(EXIT_FAILURE, "SIOCDIFADDR"); 635 } 636 if (newaddr > 0) { 637 (void) strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 638 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) == -1) 639 warn("SIOCAIFADDR"); 640 } 641 642 if (g_ifcr_updated) { 643 (void) strncpy(g_ifcr.ifcr_name, name, 644 sizeof(g_ifcr.ifcr_name)); 645 if (ioctl(s, SIOCSIFCAP, &g_ifcr) == -1) 646 err(EXIT_FAILURE, "SIOCSIFCAP"); 647 } 648 649 exit(0); 650} 651 652const struct afswtch * 653lookup_af_byname(const char *cp) 654{ 655 const struct afswtch *a; 656 657 for (a = afs; a->af_name != NULL; a++) 658 if (strcmp(a->af_name, cp) == 0) 659 return (a); 660 return (NULL); 661} 662 663const struct afswtch * 664lookup_af_bynum(int afnum) 665{ 666 const struct afswtch *a; 667 668 for (a = afs; a->af_name != NULL; a++) 669 if (a->af_af == afnum) 670 return (a); 671 return (NULL); 672} 673 674void 675getsock(int naf) 676{ 677 static int oaf = -1; 678 679 if (oaf == naf) 680 return; 681 if (oaf != -1) 682 close(s); 683 s = socket(naf, SOCK_DGRAM, 0); 684 if (s < 0) 685 oaf = -1; 686 else 687 oaf = naf; 688} 689 690int 691getinfo(struct ifreq *giifr) 692{ 693 694 getsock(af); 695 if (s < 0) 696 err(EXIT_FAILURE, "socket"); 697 if (ioctl(s, SIOCGIFFLAGS, giifr) == -1) { 698 warn("SIOCGIFFLAGS %s", giifr->ifr_name); 699 return (-1); 700 } 701 flags = giifr->ifr_flags; 702 if (ioctl(s, SIOCGIFMETRIC, giifr) == -1) { 703 warn("SIOCGIFMETRIC %s", giifr->ifr_name); 704 metric = 0; 705 } else 706 metric = giifr->ifr_metric; 707 if (ioctl(s, SIOCGIFMTU, giifr) == -1) 708 mtu = 0; 709 else 710 mtu = giifr->ifr_mtu; 711 712 memset(&g_ifcr, 0, sizeof(g_ifcr)); 713 strcpy(g_ifcr.ifcr_name, giifr->ifr_name); 714 (void) ioctl(s, SIOCGIFCAP, &g_ifcr); 715 716 return (0); 717} 718 719void 720printall(const char *ifname) 721{ 722 struct ifaddrs *ifap, *ifa; 723 struct ifreq paifr; 724 const struct sockaddr_dl *sdl = NULL; 725 int idx; 726 char *p; 727 728 if (getifaddrs(&ifap) != 0) 729 err(EXIT_FAILURE, "getifaddrs"); 730 p = NULL; 731 idx = 0; 732 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 733 memset(&paifr, 0, sizeof(paifr)); 734 strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); 735 if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 736 memcpy(&paifr.ifr_addr, ifa->ifa_addr, 737 ifa->ifa_addr->sa_len); 738 } 739 740 if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 741 continue; 742 if (ifa->ifa_addr->sa_family == AF_LINK) 743 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 744 if (p && strcmp(p, ifa->ifa_name) == 0) 745 continue; 746 if (strlcpy(name, ifa->ifa_name, sizeof(name)) >= sizeof(name)) 747 continue; 748 p = ifa->ifa_name; 749 750 if (getinfo(&paifr) < 0) 751 continue; 752 if (bflag && (ifa->ifa_flags & IFF_BROADCAST) == 0) 753 continue; 754 if (dflag && (ifa->ifa_flags & IFF_UP) != 0) 755 continue; 756 if (uflag && (ifa->ifa_flags & IFF_UP) == 0) 757 continue; 758 759 if (sflag && carrier()) 760 continue; 761 idx++; 762 /* 763 * Are we just listing the interfaces? 764 */ 765 if (lflag) { 766 if (idx > 1) 767 printf(" "); 768 fputs(name, stdout); 769 continue; 770 } 771 772 status(sdl); 773 sdl = NULL; 774 } 775 if (lflag) 776 printf("\n"); 777 freeifaddrs(ifap); 778} 779 780void 781list_cloners(void) 782{ 783 struct if_clonereq ifcr; 784 char *cp, *buf; 785 int idx; 786 787 memset(&ifcr, 0, sizeof(ifcr)); 788 789 getsock(AF_INET); 790 791 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 792 err(EXIT_FAILURE, "SIOCIFGCLONERS for count"); 793 794 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 795 if (buf == NULL) 796 err(EXIT_FAILURE, "unable to allocate cloner name buffer"); 797 798 ifcr.ifcr_count = ifcr.ifcr_total; 799 ifcr.ifcr_buffer = buf; 800 801 if (ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 802 err(EXIT_FAILURE, "SIOCIFGCLONERS for names"); 803 804 /* 805 * In case some disappeared in the mean time, clamp it down. 806 */ 807 if (ifcr.ifcr_count > ifcr.ifcr_total) 808 ifcr.ifcr_count = ifcr.ifcr_total; 809 810 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 811 if (idx > 0) 812 printf(" "); 813 printf("%s", cp); 814 } 815 816 printf("\n"); 817 free(buf); 818 return; 819} 820 821/*ARGSUSED*/ 822void 823clone_create(const char *addr, int param) 824{ 825 826 /* We're called early... */ 827 getsock(AF_INET); 828 829 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 830 if (ioctl(s, SIOCIFCREATE, &ifr) == -1) 831 err(EXIT_FAILURE, "SIOCIFCREATE"); 832} 833 834/*ARGSUSED*/ 835void 836clone_destroy(const char *addr, int param) 837{ 838 839 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 840 if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) 841 err(EXIT_FAILURE, "SIOCIFDESTROY"); 842} 843 844/*ARGSUSED*/ 845void 846setifaddr(const char *addr, int param) 847{ 848 struct ifreq *siifr; /* XXX */ 849 850 /* 851 * Delay the ioctl to set the interface addr until flags are all set. 852 * The address interpretation may depend on the flags, 853 * and the flags may change when the address is set. 854 */ 855 setaddr++; 856 if (newaddr == -1) 857 newaddr = 1; 858 if (doalias == 0 && afp->af_gifaddr != 0) { 859 siifr = (struct ifreq *)afp->af_ridreq; 860 (void) strncpy(siifr->ifr_name, name, sizeof(siifr->ifr_name)); 861 siifr->ifr_addr.sa_family = afp->af_af; 862 if (ioctl(s, afp->af_gifaddr, afp->af_ridreq) == 0) 863 clearaddr = 1; 864 else if (errno == EADDRNOTAVAIL) 865 /* No address was assigned yet. */ 866 ; 867 else 868 err(EXIT_FAILURE, "SIOCGIFADDR"); 869 } 870 871 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 872} 873 874void 875setifnetmask(const char *addr, int d) 876{ 877 (*afp->af_getaddr)(addr, MASK); 878} 879 880void 881setifbroadaddr(const char *addr, int d) 882{ 883 (*afp->af_getaddr)(addr, DSTADDR); 884} 885 886void 887setifipdst(const char *addr, int d) 888{ 889 in_getaddr(addr, DSTADDR); 890 setipdst++; 891 clearaddr = 0; 892 newaddr = 0; 893} 894 895#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 896/*ARGSUSED*/ 897void 898notealias(const char *addr, int param) 899{ 900 if (setaddr && doalias == 0 && param < 0) 901 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), 902 rqtosa(af_addreq)->sa_len); 903 doalias = param; 904 if (param < 0) { 905 clearaddr = 1; 906 newaddr = 0; 907 conflicting++; 908 } else { 909 clearaddr = 0; 910 conflicting++; 911 } 912} 913 914/*ARGSUSED*/ 915void 916notrailers(const char *vname, int value) 917{ 918 puts("Note: trailers are no longer sent, but always received"); 919} 920 921/*ARGSUSED*/ 922void 923setifdstaddr(const char *addr, int param) 924{ 925 (*afp->af_getaddr)(addr, DSTADDR); 926} 927 928void 929setifflags(const char *vname, int value) 930{ 931 struct ifreq ifreq; 932 933 (void) strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); 934 if (ioctl(s, SIOCGIFFLAGS, &ifreq) == -1) 935 err(EXIT_FAILURE, "SIOCGIFFLAGS"); 936 flags = ifreq.ifr_flags; 937 938 if (value < 0) { 939 value = -value; 940 flags &= ~value; 941 } else 942 flags |= value; 943 ifreq.ifr_flags = flags; 944 if (ioctl(s, SIOCSIFFLAGS, &ifreq) == -1) 945 err(EXIT_FAILURE, "SIOCSIFFLAGS"); 946} 947 948void 949setifcaps(const char *vname, int value) 950{ 951 952 if (value < 0) { 953 value = -value; 954 g_ifcr.ifcr_capenable &= ~value; 955 } else 956 g_ifcr.ifcr_capenable |= value; 957 958 g_ifcr_updated = 1; 959} 960 961#ifdef INET6 962void 963setia6flags(const char *vname, int value) 964{ 965 966 if (value < 0) { 967 value = -value; 968 in6_addreq.ifra_flags &= ~value; 969 } else 970 in6_addreq.ifra_flags |= value; 971} 972 973void 974setia6pltime(const char *val, int d) 975{ 976 977 setia6lifetime("pltime", val); 978} 979 980void 981setia6vltime(const char *val, int d) 982{ 983 984 setia6lifetime("vltime", val); 985} 986 987void 988setia6lifetime(const char *cmd, const char *val) 989{ 990 time_t newval, t; 991 char *ep; 992 993 t = time(NULL); 994 newval = (time_t)strtoul(val, &ep, 0); 995 if (val == ep) 996 errx(EXIT_FAILURE, "invalid %s", cmd); 997 if (afp->af_af != AF_INET6) 998 errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); 999 if (strcmp(cmd, "vltime") == 0) { 1000 in6_addreq.ifra_lifetime.ia6t_expire = t + newval; 1001 in6_addreq.ifra_lifetime.ia6t_vltime = newval; 1002 } else if (strcmp(cmd, "pltime") == 0) { 1003 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; 1004 in6_addreq.ifra_lifetime.ia6t_pltime = newval; 1005 } 1006} 1007 1008void 1009setia6eui64(const char *cmd, int val) 1010{ 1011 struct ifaddrs *ifap, *ifa; 1012 const struct sockaddr_in6 *sin6 = NULL; 1013 const struct in6_addr *lladdr = NULL; 1014 struct in6_addr *in6; 1015 1016 if (afp->af_af != AF_INET6) 1017 errx(EXIT_FAILURE, "%s not allowed for the AF", cmd); 1018 in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; 1019 if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) 1020 errx(EXIT_FAILURE, "interface index is already filled"); 1021 if (getifaddrs(&ifap) != 0) 1022 err(EXIT_FAILURE, "getifaddrs"); 1023 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1024 if (ifa->ifa_addr->sa_family == AF_INET6 && 1025 strcmp(ifa->ifa_name, name) == 0) { 1026 sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; 1027 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1028 lladdr = &sin6->sin6_addr; 1029 break; 1030 } 1031 } 1032 } 1033 if (!lladdr) 1034 errx(EXIT_FAILURE, "could not determine link local address"); 1035 1036 memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); 1037 1038 freeifaddrs(ifap); 1039} 1040#endif 1041 1042void 1043setifmetric(const char *val, int d) 1044{ 1045 char *ep = NULL; 1046 1047 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1048 ifr.ifr_metric = strtoul(val, &ep, 10); 1049 if (!ep || *ep) 1050 errx(EXIT_FAILURE, "%s: invalid metric", val); 1051 if (ioctl(s, SIOCSIFMETRIC, &ifr) == -1) 1052 warn("SIOCSIFMETRIC"); 1053} 1054 1055void 1056setifmtu(const char *val, int d) 1057{ 1058 char *ep = NULL; 1059 1060 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1061 ifr.ifr_mtu = strtoul(val, &ep, 10); 1062 if (!ep || *ep) 1063 errx(EXIT_FAILURE, "%s: invalid mtu", val); 1064 if (ioctl(s, SIOCSIFMTU, &ifr) == -1) 1065 warn("SIOCSIFMTU"); 1066} 1067 1068const char * 1069get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) 1070{ 1071 int len; 1072 int hexstr; 1073 u_int8_t *p; 1074 1075 len = *lenp; 1076 p = buf; 1077 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); 1078 if (hexstr) 1079 val += 2; 1080 for (;;) { 1081 if (*val == '\0') 1082 break; 1083 if (sep != NULL && strchr(sep, *val) != NULL) { 1084 val++; 1085 break; 1086 } 1087 if (hexstr) { 1088 if (!isxdigit((u_char)val[0]) || 1089 !isxdigit((u_char)val[1])) { 1090 warnx("bad hexadecimal digits"); 1091 return NULL; 1092 } 1093 } 1094 if (p > buf + len) { 1095 if (hexstr) 1096 warnx("hexadecimal digits too long"); 1097 else 1098 warnx("strings too long"); 1099 return NULL; 1100 } 1101 if (hexstr) { 1102#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) 1103 *p++ = (tohex((u_char)val[0]) << 4) | 1104 tohex((u_char)val[1]); 1105#undef tohex 1106 val += 2; 1107 } else 1108 *p++ = *val++; 1109 } 1110 len = p - buf; 1111 if (len < *lenp) 1112 memset(p, 0, *lenp - len); 1113 *lenp = len; 1114 return val; 1115} 1116 1117void 1118print_string(const u_int8_t *buf, int len) 1119{ 1120 int i; 1121 int hasspc; 1122 1123 i = 0; 1124 hasspc = 0; 1125 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { 1126 for (; i < len; i++) { 1127 if (!isprint(buf[i])) 1128 break; 1129 if (isspace(buf[i])) 1130 hasspc++; 1131 } 1132 } 1133 if (i == len) { 1134 if (hasspc || len == 0) 1135 printf("\"%.*s\"", len, buf); 1136 else 1137 printf("%.*s", len, buf); 1138 } else { 1139 printf("0x"); 1140 for (i = 0; i < len; i++) 1141 printf("%02x", buf[i]); 1142 } 1143} 1144 1145static void 1146media_error(int type, const char *val, const char *opt) 1147{ 1148 errx(EXIT_FAILURE, "unknown %s media %s: %s", 1149 get_media_type_string(type), opt, val); 1150} 1151 1152void 1153init_current_media(void) 1154{ 1155 struct ifmediareq ifmr; 1156 1157 /* 1158 * If we have not yet done so, grab the currently-selected 1159 * media. 1160 */ 1161 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { 1162 (void) memset(&ifmr, 0, sizeof(ifmr)); 1163 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1164 1165 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) { 1166 /* 1167 * If we get E2BIG, the kernel is telling us 1168 * that there are more, so we can ignore it. 1169 */ 1170 if (errno != E2BIG) 1171 err(EXIT_FAILURE, "SGIOCGIFMEDIA"); 1172 } 1173 1174 media_current = ifmr.ifm_current; 1175 } 1176 1177 /* Sanity. */ 1178 if (IFM_TYPE(media_current) == 0) 1179 errx(EXIT_FAILURE, "%s: no link type?", name); 1180} 1181 1182void 1183process_media_commands(void) 1184{ 1185 1186 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { 1187 /* Nothing to do. */ 1188 return; 1189 } 1190 1191 /* 1192 * Media already set up, and commands sanity-checked. Set/clear 1193 * any options, and we're ready to go. 1194 */ 1195 media_current |= mediaopt_set; 1196 media_current &= ~mediaopt_clear; 1197 1198 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1199 ifr.ifr_media = media_current; 1200 1201 if (ioctl(s, SIOCSIFMEDIA, &ifr) == -1) 1202 err(EXIT_FAILURE, "SIOCSIFMEDIA"); 1203} 1204 1205void 1206setmedia(const char *val, int d) 1207{ 1208 int type, subtype, inst; 1209 1210 init_current_media(); 1211 1212 /* Only one media command may be given. */ 1213 if (actions & A_MEDIA) 1214 errx(EXIT_FAILURE, "only one `media' command may be issued"); 1215 1216 /* Must not come after mode commands */ 1217 if (actions & A_MEDIAMODE) 1218 errx(EXIT_FAILURE, 1219 "may not issue `media' after `mode' commands"); 1220 1221 /* Must not come after mediaopt commands */ 1222 if (actions & A_MEDIAOPT) 1223 errx(EXIT_FAILURE, 1224 "may not issue `media' after `mediaopt' commands"); 1225 1226 /* 1227 * No need to check if `instance' has been issued; setmediainst() 1228 * craps out if `media' has not been specified. 1229 */ 1230 1231 type = IFM_TYPE(media_current); 1232 inst = IFM_INST(media_current); 1233 1234 /* Look up the subtype. */ 1235 subtype = get_media_subtype(type, val); 1236 if (subtype == -1) 1237 media_error(type, val, "subtype"); 1238 1239 /* Build the new current media word. */ 1240 media_current = IFM_MAKEWORD(type, subtype, 0, inst); 1241 1242 /* Media will be set after other processing is complete. */ 1243} 1244 1245void 1246setmediaopt(const char *val, int d) 1247{ 1248 char *invalid; 1249 1250 init_current_media(); 1251 1252 /* Can only issue `mediaopt' once. */ 1253 if (actions & A_MEDIAOPTSET) 1254 errx(EXIT_FAILURE, "only one `mediaopt' command may be issued"); 1255 1256 /* Can't issue `mediaopt' if `instance' has already been issued. */ 1257 if (actions & A_MEDIAINST) 1258 errx(EXIT_FAILURE, "may not issue `mediaopt' after `instance'"); 1259 1260 mediaopt_set = get_media_options(media_current, val, &invalid); 1261 if (mediaopt_set == -1) 1262 media_error(media_current, invalid, "option"); 1263 1264 /* Media will be set after other processing is complete. */ 1265} 1266 1267void 1268unsetmediaopt(const char *val, int d) 1269{ 1270 char *invalid; 1271 1272 init_current_media(); 1273 1274 /* Can only issue `-mediaopt' once. */ 1275 if (actions & A_MEDIAOPTCLR) 1276 errx(EXIT_FAILURE, 1277 "only one `-mediaopt' command may be issued"); 1278 1279 /* May not issue `media' and `-mediaopt'. */ 1280 if (actions & A_MEDIA) 1281 errx(EXIT_FAILURE, 1282 "may not issue both `media' and `-mediaopt'"); 1283 1284 /* 1285 * No need to check for A_MEDIAINST, since the test for A_MEDIA 1286 * implicitly checks for A_MEDIAINST. 1287 */ 1288 1289 mediaopt_clear = get_media_options(media_current, val, &invalid); 1290 if (mediaopt_clear == -1) 1291 media_error(media_current, invalid, "option"); 1292 1293 /* Media will be set after other processing is complete. */ 1294} 1295 1296void 1297setmediainst(const char *val, int d) 1298{ 1299 int type, subtype, options, inst; 1300 1301 init_current_media(); 1302 1303 /* Can only issue `instance' once. */ 1304 if (actions & A_MEDIAINST) 1305 errx(EXIT_FAILURE, "only one `instance' command may be issued"); 1306 1307 /* Must have already specified `media' */ 1308 if ((actions & A_MEDIA) == 0) 1309 errx(EXIT_FAILURE, "must specify `media' before `instance'"); 1310 1311 type = IFM_TYPE(media_current); 1312 subtype = IFM_SUBTYPE(media_current); 1313 options = IFM_OPTIONS(media_current); 1314 1315 inst = atoi(val); 1316 if (inst < 0 || inst > IFM_INST_MAX) 1317 errx(EXIT_FAILURE, "invalid media instance: %s", val); 1318 1319 media_current = IFM_MAKEWORD(type, subtype, options, inst); 1320 1321 /* Media will be set after other processing is complete. */ 1322} 1323 1324void 1325setmediamode(const char *val, int d) 1326{ 1327 int type, subtype, options, inst, mode; 1328 1329 init_current_media(); 1330 1331 /* Can only issue `mode' once. */ 1332 if (actions & A_MEDIAMODE) 1333 errx(EXIT_FAILURE, "only one `mode' command may be issued"); 1334 1335 type = IFM_TYPE(media_current); 1336 subtype = IFM_SUBTYPE(media_current); 1337 options = IFM_OPTIONS(media_current); 1338 inst = IFM_INST(media_current); 1339 1340 mode = get_media_mode(type, val); 1341 if (mode == -1) 1342 media_error(type, val, "mode"); 1343 1344 media_current = IFM_MAKEWORD(type, subtype, options, inst) | mode; 1345 1346 /* Media will be set after other processing is complete. */ 1347} 1348 1349void 1350print_media_word(int ifmw, const char *opt_sep) 1351{ 1352 const char *str; 1353 1354 printf("%s", get_media_subtype_string(ifmw)); 1355 1356 /* Find mode. */ 1357 if (IFM_MODE(ifmw) != 0) { 1358 str = get_media_mode_string(ifmw); 1359 if (str != NULL) 1360 printf(" mode %s", str); 1361 } 1362 1363 /* Find options. */ 1364 for (; (str = get_media_option_string(&ifmw)) != NULL; opt_sep = ",") 1365 printf("%s%s", opt_sep, str); 1366 1367 if (IFM_INST(ifmw) != 0) 1368 printf(" instance %d", IFM_INST(ifmw)); 1369} 1370 1371int 1372carrier(void) 1373{ 1374 struct ifmediareq ifmr; 1375 1376 (void) memset(&ifmr, 0, sizeof(ifmr)); 1377 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1378 1379 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) { 1380 /* 1381 * Interface doesn't support SIOC{G,S}IFMEDIA; 1382 * assume ok. 1383 */ 1384 return 0; 1385 } 1386 if ((ifmr.ifm_status & IFM_AVALID) == 0) { 1387 /* 1388 * Interface doesn't report media-valid status. 1389 * assume ok. 1390 */ 1391 return 0; 1392 } 1393 /* otherwise, return ok for active, not-ok if not active. */ 1394 return !(ifmr.ifm_status & IFM_ACTIVE); 1395} 1396 1397 1398#define IFFBITS \ 1399"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 1400\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 1401 1402#define IFCAPBITS \ 1403"\020\1IP4CSUM\2TCP4CSUM\3UDP4CSUM\4TCP6CSUM\5UDP6CSUM\6TCP4CSUM_Rx\7UDP4CSUM_Rx\10TSO4" 1404 1405const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 1406 1407const struct ifmedia_status_description ifm_status_descriptions[] = 1408 IFM_STATUS_DESCRIPTIONS; 1409 1410/* 1411 * Print the status of the interface. If an address family was 1412 * specified, show it and it only; otherwise, show them all. 1413 */ 1414void 1415status(const struct sockaddr_dl *sdl) 1416{ 1417 const struct afswtch *p = afp; 1418 struct ifmediareq ifmr; 1419 struct ifdatareq ifdr; 1420 int *media_list, i; 1421 char hbuf[NI_MAXHOST]; 1422 char fbuf[BUFSIZ]; 1423 1424 (void)snprintb(fbuf, sizeof(fbuf), IFFBITS, flags); 1425 printf("%s: flags=%s", name, &fbuf[2]); 1426 if (metric) 1427 printf(" metric %lu", metric); 1428 if (mtu) 1429 printf(" mtu %lu", mtu); 1430 printf("\n"); 1431 1432 if (g_ifcr.ifcr_capabilities) { 1433 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS, 1434 g_ifcr.ifcr_capabilities); 1435 printf("\tcapabilities=%s\n", &fbuf[2]); 1436 (void)snprintb(fbuf, sizeof(fbuf), IFCAPBITS, 1437 g_ifcr.ifcr_capenable); 1438 printf("\tenabled=%s\n", &fbuf[2]); 1439 } 1440 1441 ieee80211_status(); 1442 vlan_status(); 1443 tunnel_status(); 1444 agr_status(); 1445 1446 if (sdl != NULL && 1447 getnameinfo((const struct sockaddr *)sdl, sdl->sdl_len, 1448 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) == 0 && 1449 hbuf[0] != '\0') 1450 printf("\taddress: %s\n", hbuf); 1451 1452 (void) memset(&ifmr, 0, sizeof(ifmr)); 1453 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1454 1455 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) { 1456 /* 1457 * Interface doesn't support SIOC{G,S}IFMEDIA. 1458 */ 1459 goto iface_stats; 1460 } 1461 1462 if (ifmr.ifm_count == 0) { 1463 warnx("%s: no media types?", name); 1464 goto iface_stats; 1465 } 1466 1467 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 1468 if (media_list == NULL) 1469 err(EXIT_FAILURE, "malloc"); 1470 ifmr.ifm_ulist = media_list; 1471 1472 if (ioctl(s, SIOCGIFMEDIA, &ifmr) == -1) 1473 err(EXIT_FAILURE, "SIOCGIFMEDIA"); 1474 1475 printf("\tmedia: %s ", get_media_type_string(ifmr.ifm_current)); 1476 print_media_word(ifmr.ifm_current, " "); 1477 if (ifmr.ifm_active != ifmr.ifm_current) { 1478 printf(" ("); 1479 print_media_word(ifmr.ifm_active, " "); 1480 printf(")"); 1481 } 1482 printf("\n"); 1483 1484 if (ifmr.ifm_status & IFM_STATUS_VALID) { 1485 const struct ifmedia_status_description *ifms; 1486 int bitno, found = 0; 1487 1488 printf("\tstatus: "); 1489 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { 1490 for (ifms = ifm_status_descriptions; 1491 ifms->ifms_valid != 0; ifms++) { 1492 if (ifms->ifms_type != 1493 IFM_TYPE(ifmr.ifm_current) || 1494 ifms->ifms_valid != 1495 ifm_status_valid_list[bitno]) 1496 continue; 1497 printf("%s%s", found ? ", " : "", 1498 IFM_STATUS_DESC(ifms, ifmr.ifm_status)); 1499 found = 1; 1500 1501 /* 1502 * For each valid indicator bit, there's 1503 * only one entry for each media type, so 1504 * terminate the inner loop now. 1505 */ 1506 break; 1507 } 1508 } 1509 1510 if (found == 0) 1511 printf("unknown"); 1512 printf("\n"); 1513 } 1514 1515 if (mflag) { 1516 int type, printed_type; 1517 1518 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) { 1519 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { 1520 if (IFM_TYPE(media_list[i]) != type) 1521 continue; 1522 if (printed_type == 0) { 1523 printf("\tsupported %s media:\n", 1524 get_media_type_string(type)); 1525 printed_type = 1; 1526 } 1527 printf("\t\tmedia "); 1528 print_media_word(media_list[i], " mediaopt "); 1529 printf("\n"); 1530 } 1531 } 1532 } 1533 1534 free(media_list); 1535 1536 iface_stats: 1537 if (!vflag && !zflag) 1538 goto proto_status; 1539 1540 (void) strncpy(ifdr.ifdr_name, name, sizeof(ifdr.ifdr_name)); 1541 1542 if (ioctl(s, zflag ? SIOCZIFDATA:SIOCGIFDATA, &ifdr) == -1) { 1543 err(EXIT_FAILURE, zflag ? "SIOCZIFDATA" : "SIOCGIFDATA"); 1544 } else { 1545 struct if_data * const ifi = &ifdr.ifdr_data; 1546#define PLURAL(n) ((n) == 1 ? "" : "s") 1547 printf("\tinput: %llu packet%s, %llu byte%s", 1548 (unsigned long long) ifi->ifi_ipackets, 1549 PLURAL(ifi->ifi_ipackets), 1550 (unsigned long long) ifi->ifi_ibytes, 1551 PLURAL(ifi->ifi_ibytes)); 1552 if (ifi->ifi_imcasts) 1553 printf(", %llu multicast%s", 1554 (unsigned long long) ifi->ifi_imcasts, 1555 PLURAL(ifi->ifi_imcasts)); 1556 if (ifi->ifi_ierrors) 1557 printf(", %llu error%s", 1558 (unsigned long long) ifi->ifi_ierrors, 1559 PLURAL(ifi->ifi_ierrors)); 1560 if (ifi->ifi_iqdrops) 1561 printf(", %llu queue drop%s", 1562 (unsigned long long) ifi->ifi_iqdrops, 1563 PLURAL(ifi->ifi_iqdrops)); 1564 if (ifi->ifi_noproto) 1565 printf(", %llu unknown protocol", 1566 (unsigned long long) ifi->ifi_noproto); 1567 printf("\n\toutput: %llu packet%s, %llu byte%s", 1568 (unsigned long long) ifi->ifi_opackets, 1569 PLURAL(ifi->ifi_opackets), 1570 (unsigned long long) ifi->ifi_obytes, 1571 PLURAL(ifi->ifi_obytes)); 1572 if (ifi->ifi_omcasts) 1573 printf(", %llu multicast%s", 1574 (unsigned long long) ifi->ifi_omcasts, 1575 PLURAL(ifi->ifi_omcasts)); 1576 if (ifi->ifi_oerrors) 1577 printf(", %llu error%s", 1578 (unsigned long long) ifi->ifi_oerrors, 1579 PLURAL(ifi->ifi_oerrors)); 1580 if (ifi->ifi_collisions) 1581 printf(", %llu collision%s", 1582 (unsigned long long) ifi->ifi_collisions, 1583 PLURAL(ifi->ifi_collisions)); 1584 printf("\n"); 1585#undef PLURAL 1586 } 1587 1588 ieee80211_statistics(); 1589 1590 proto_status: 1591 if ((p = afp) != NULL) { 1592 (*p->af_status)(1); 1593 } else for (p = afs; p->af_name; p++) { 1594 ifr.ifr_addr.sa_family = p->af_af; 1595 (*p->af_status)(0); 1596 } 1597} 1598 1599void 1600in_alias(struct ifreq *creq) 1601{ 1602 struct sockaddr_in *iasin; 1603 int alias; 1604 1605 if (lflag) 1606 return; 1607 1608 alias = 1; 1609 1610 /* Get the non-alias address for this interface. */ 1611 getsock(AF_INET); 1612 if (s < 0) { 1613 if (errno == EPROTONOSUPPORT) 1614 return; 1615 err(EXIT_FAILURE, "socket"); 1616 } 1617 (void) memset(&ifr, 0, sizeof(ifr)); 1618 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1619 if (ioctl(s, SIOCGIFADDR, &ifr) == -1) { 1620 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1621 return; 1622 } else 1623 warn("SIOCGIFADDR"); 1624 } 1625 /* If creq and ifr are the same address, this is not an alias. */ 1626 if (memcmp(&ifr.ifr_addr, &creq->ifr_addr, 1627 sizeof(creq->ifr_addr)) == 0) 1628 alias = 0; 1629 (void) memset(&in_addreq, 0, sizeof(in_addreq)); 1630 (void) strncpy(in_addreq.ifra_name, name, sizeof(in_addreq.ifra_name)); 1631 memcpy(&in_addreq.ifra_addr, &creq->ifr_addr, 1632 sizeof(in_addreq.ifra_addr)); 1633 if (ioctl(s, SIOCGIFALIAS, &in_addreq) == -1) { 1634 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1635 return; 1636 } else 1637 warn("SIOCGIFALIAS"); 1638 } 1639 1640 iasin = &in_addreq.ifra_addr; 1641 printf("\tinet %s%s", alias ? "alias " : "", inet_ntoa(iasin->sin_addr)); 1642 1643 if (flags & IFF_POINTOPOINT) { 1644 iasin = &in_addreq.ifra_dstaddr; 1645 printf(" -> %s", inet_ntoa(iasin->sin_addr)); 1646 } 1647 1648 iasin = &in_addreq.ifra_mask; 1649 printf(" netmask 0x%x", ntohl(iasin->sin_addr.s_addr)); 1650 1651 if (flags & IFF_BROADCAST) { 1652 iasin = &in_addreq.ifra_broadaddr; 1653 printf(" broadcast %s", inet_ntoa(iasin->sin_addr)); 1654 } 1655 printf("\n"); 1656} 1657 1658void 1659in_status(int force) 1660{ 1661 struct ifaddrs *ifap, *ifa; 1662 struct ifreq isifr; 1663 1664 if (getifaddrs(&ifap) != 0) 1665 err(EXIT_FAILURE, "getifaddrs"); 1666 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1667 if (strcmp(name, ifa->ifa_name) != 0) 1668 continue; 1669 if (ifa->ifa_addr->sa_family != AF_INET) 1670 continue; 1671 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len) 1672 continue; 1673 1674 memset(&isifr, 0, sizeof(isifr)); 1675 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name)); 1676 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 1677 in_alias(&isifr); 1678 } 1679 freeifaddrs(ifap); 1680} 1681 1682void 1683setifprefixlen(const char *addr, int d) 1684{ 1685 if (*afp->af_getprefix) 1686 (*afp->af_getprefix)(addr, MASK); 1687 explicit_prefix = 1; 1688} 1689 1690#ifdef INET6 1691void 1692in6_fillscopeid(struct sockaddr_in6 *sin6) 1693{ 1694#if defined(__KAME__) && defined(KAME_SCOPEID) 1695 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1696 sin6->sin6_scope_id = 1697 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 1698 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 1699 } 1700#endif 1701} 1702 1703/* XXX not really an alias */ 1704void 1705in6_alias(struct in6_ifreq *creq) 1706{ 1707 struct sockaddr_in6 *sin6; 1708 char hbuf[NI_MAXHOST]; 1709 u_int32_t scopeid; 1710 const int niflag = NI_NUMERICHOST; 1711 1712 /* Get the non-alias address for this interface. */ 1713 getsock(AF_INET6); 1714 if (s < 0) { 1715 if (errno == EPROTONOSUPPORT) 1716 return; 1717 err(EXIT_FAILURE, "socket"); 1718 } 1719 1720 sin6 = (struct sockaddr_in6 *)&creq->ifr_addr; 1721 1722 in6_fillscopeid(sin6); 1723 scopeid = sin6->sin6_scope_id; 1724 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 1725 hbuf, sizeof(hbuf), NULL, 0, niflag)) 1726 strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */ 1727 printf("\tinet6 %s", hbuf); 1728 1729 if (flags & IFF_POINTOPOINT) { 1730 (void) memset(&ifr6, 0, sizeof(ifr6)); 1731 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1732 ifr6.ifr_addr = creq->ifr_addr; 1733 if (ioctl(s, SIOCGIFDSTADDR_IN6, &ifr6) == -1) { 1734 if (errno != EADDRNOTAVAIL) 1735 warn("SIOCGIFDSTADDR_IN6"); 1736 (void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr)); 1737 ifr6.ifr_addr.sin6_family = AF_INET6; 1738 ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6); 1739 } 1740 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 1741 in6_fillscopeid(sin6); 1742 hbuf[0] = '\0'; 1743 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 1744 hbuf, sizeof(hbuf), NULL, 0, niflag)) 1745 strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */ 1746 printf(" -> %s", hbuf); 1747 } 1748 1749 (void) memset(&ifr6, 0, sizeof(ifr6)); 1750 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1751 ifr6.ifr_addr = creq->ifr_addr; 1752 if (ioctl(s, SIOCGIFNETMASK_IN6, &ifr6) == -1) { 1753 if (errno != EADDRNOTAVAIL) 1754 warn("SIOCGIFNETMASK_IN6"); 1755 } else { 1756 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 1757 printf(" prefixlen %d", prefix(&sin6->sin6_addr, 1758 sizeof(struct in6_addr))); 1759 } 1760 1761 (void) memset(&ifr6, 0, sizeof(ifr6)); 1762 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1763 ifr6.ifr_addr = creq->ifr_addr; 1764 if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == -1) { 1765 if (errno != EADDRNOTAVAIL) 1766 warn("SIOCGIFAFLAG_IN6"); 1767 } else { 1768 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST) 1769 printf(" anycast"); 1770 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) 1771 printf(" tentative"); 1772 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) 1773 printf(" duplicated"); 1774 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED) 1775 printf(" detached"); 1776 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) 1777 printf(" deprecated"); 1778 } 1779 1780 if (scopeid) 1781 printf(" scopeid 0x%x", scopeid); 1782 1783 if (Lflag) { 1784 struct in6_addrlifetime *lifetime; 1785 (void) memset(&ifr6, 0, sizeof(ifr6)); 1786 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1787 ifr6.ifr_addr = creq->ifr_addr; 1788 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 1789 if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1) { 1790 if (errno != EADDRNOTAVAIL) 1791 warn("SIOCGIFALIFETIME_IN6"); 1792 } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { 1793 time_t t = time(NULL); 1794 printf(" pltime "); 1795 if (lifetime->ia6t_preferred) { 1796 printf("%s", lifetime->ia6t_preferred < t 1797 ? "0" 1798 : sec2str(lifetime->ia6t_preferred - t)); 1799 } else 1800 printf("infty"); 1801 1802 printf(" vltime "); 1803 if (lifetime->ia6t_expire) { 1804 printf("%s", lifetime->ia6t_expire < t 1805 ? "0" 1806 : sec2str(lifetime->ia6t_expire - t)); 1807 } else 1808 printf("infty"); 1809 } 1810 } 1811 1812 printf("\n"); 1813} 1814 1815void 1816in6_status(int force) 1817{ 1818 struct ifaddrs *ifap, *ifa; 1819 struct in6_ifreq isifr; 1820 1821 if (getifaddrs(&ifap) != 0) 1822 err(EXIT_FAILURE, "getifaddrs"); 1823 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1824 if (strcmp(name, ifa->ifa_name) != 0) 1825 continue; 1826 if (ifa->ifa_addr->sa_family != AF_INET6) 1827 continue; 1828 if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len) 1829 continue; 1830 1831 memset(&isifr, 0, sizeof(isifr)); 1832 strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name)); 1833 memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 1834 in6_alias(&isifr); 1835 } 1836 freeifaddrs(ifap); 1837} 1838#endif /*INET6*/ 1839 1840#ifndef INET_ONLY 1841 1842void 1843xns_status(int force) 1844{ 1845 struct sockaddr_ns *sns; 1846 1847 getsock(AF_NS); 1848 if (s < 0) { 1849 if (errno == EPROTONOSUPPORT) 1850 return; 1851 err(EXIT_FAILURE, "socket"); 1852 } 1853 (void) memset(&ifr, 0, sizeof(ifr)); 1854 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1855 if (ioctl(s, SIOCGIFADDR, &ifr) == -1) { 1856 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1857 if (!force) 1858 return; 1859 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1860 } else 1861 warn("SIOCGIFADDR"); 1862 } 1863 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 1864 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 1865 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1866 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 1867 if (ioctl(s, SIOCGIFDSTADDR, &ifr) == -1) { 1868 if (errno == EADDRNOTAVAIL) 1869 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1870 else 1871 warn("SIOCGIFDSTADDR"); 1872 } 1873 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1874 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 1875 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1876 } 1877 printf("\n"); 1878} 1879 1880void 1881iso_status(int force) 1882{ 1883 struct sockaddr_iso *siso; 1884 struct iso_ifreq isoifr; 1885 1886 getsock(AF_ISO); 1887 if (s < 0) { 1888 if (errno == EPROTONOSUPPORT) 1889 return; 1890 err(EXIT_FAILURE, "socket"); 1891 } 1892 (void) memset(&isoifr, 0, sizeof(isoifr)); 1893 (void) strncpy(isoifr.ifr_name, name, sizeof(isoifr.ifr_name)); 1894 if (ioctl(s, SIOCGIFADDR_ISO, &isoifr) == -1) { 1895 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1896 if (!force) 1897 return; 1898 (void) memset(&isoifr.ifr_Addr, 0, 1899 sizeof(isoifr.ifr_Addr)); 1900 } else 1901 warn("SIOCGIFADDR_ISO"); 1902 } 1903 (void) strncpy(isoifr.ifr_name, name, sizeof isoifr.ifr_name); 1904 siso = &isoifr.ifr_Addr; 1905 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 1906 if (ioctl(s, SIOCGIFNETMASK_ISO, &isoifr) == -1) { 1907 if (errno == EADDRNOTAVAIL) 1908 memset(&isoifr.ifr_Addr, 0, sizeof(isoifr.ifr_Addr)); 1909 else 1910 warn("SIOCGIFNETMASK_ISO"); 1911 } else { 1912 if (siso->siso_len > offsetof(struct sockaddr_iso, siso_addr)) 1913 siso->siso_addr.isoa_len = siso->siso_len 1914 - offsetof(struct sockaddr_iso, siso_addr); 1915 printf("\n\t\tnetmask %s ", iso_ntoa(&siso->siso_addr)); 1916 } 1917 if (flags & IFF_POINTOPOINT) { 1918 if (ioctl(s, SIOCGIFDSTADDR_ISO, &isoifr) == -1) { 1919 if (errno == EADDRNOTAVAIL) 1920 memset(&isoifr.ifr_Addr, 0, 1921 sizeof(isoifr.ifr_Addr)); 1922 else 1923 warn("SIOCGIFDSTADDR_ISO"); 1924 } 1925 (void) strncpy(isoifr.ifr_name, name, sizeof (isoifr.ifr_name)); 1926 siso = &isoifr.ifr_Addr; 1927 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 1928 } 1929 printf("\n"); 1930} 1931 1932#endif /* INET_ONLY */ 1933 1934#define SIN(x) ((struct sockaddr_in *) &(x)) 1935struct sockaddr_in *sintab[] = { 1936 SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr), 1937 SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)}; 1938 1939void 1940in_getaddr(const char *str, int which) 1941{ 1942 struct sockaddr_in *gasin = sintab[which]; 1943 struct hostent *hp; 1944 struct netent *np; 1945 1946 gasin->sin_len = sizeof(*gasin); 1947 if (which != MASK) 1948 gasin->sin_family = AF_INET; 1949 1950 if (which == ADDR) { 1951 char *p = NULL; 1952 if ((p = strrchr(str, '/')) != NULL) { 1953 *p = '\0'; 1954 in_getprefix(p + 1, MASK); 1955 } 1956 } 1957 1958 if (inet_aton(str, &gasin->sin_addr) == 0) { 1959 if ((hp = gethostbyname(str)) != NULL) 1960 (void) memcpy(&gasin->sin_addr, hp->h_addr, hp->h_length); 1961 else if ((np = getnetbyname(str)) != NULL) 1962 gasin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1963 else 1964 errx(EXIT_FAILURE, "%s: bad value", str); 1965 } 1966} 1967 1968void 1969in_getprefix(const char *plen, int which) 1970{ 1971 struct sockaddr_in *igsin = sintab[which]; 1972 u_char *cp; 1973 int len = strtol(plen, (char **)NULL, 10); 1974 1975 if ((len < 0) || (len > 32)) 1976 errx(EXIT_FAILURE, "%s: bad value", plen); 1977 igsin->sin_len = sizeof(*igsin); 1978 if (which != MASK) 1979 igsin->sin_family = AF_INET; 1980 if ((len == 0) || (len == 32)) { 1981 memset(&igsin->sin_addr, 0xff, sizeof(struct in_addr)); 1982 return; 1983 } 1984 memset((void *)&igsin->sin_addr, 0x00, sizeof(igsin->sin_addr)); 1985 for (cp = (u_char *)&igsin->sin_addr; len > 7; len -= 8) 1986 *cp++ = 0xff; 1987 if (len) 1988 *cp = 0xff << (8 - len); 1989} 1990 1991#ifdef INET6 1992#define SIN6(x) ((struct sockaddr_in6 *) &(x)) 1993struct sockaddr_in6 *sin6tab[] = { 1994 SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 1995 SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 1996 1997void 1998in6_getaddr(const char *str, int which) 1999{ 2000#if defined(__KAME__) && defined(KAME_SCOPEID) 2001 struct sockaddr_in6 *sin6 = sin6tab[which]; 2002 struct addrinfo hints, *res; 2003 int error; 2004 char *slash = NULL; 2005 2006 if (which == ADDR) { 2007 if ((slash = strrchr(str, '/')) != NULL) 2008 *slash = '\0'; 2009 } 2010 2011 memset(&hints, 0, sizeof(hints)); 2012 hints.ai_family = AF_INET6; 2013 hints.ai_socktype = SOCK_DGRAM; 2014#if 0 /* in_getaddr() allows FQDN */ 2015 hints.ai_flags = AI_NUMERICHOST; 2016#endif 2017 error = getaddrinfo(str, "0", &hints, &res); 2018 if (error && slash) { 2019 /* try again treating the '/' as part of the name */ 2020 *slash = '/'; 2021 slash = NULL; 2022 error = getaddrinfo(str, "0", &hints, &res); 2023 } 2024 if (error) 2025 errx(EXIT_FAILURE, "%s: %s", str, gai_strerror(error)); 2026 if (res->ai_next) 2027 errx(EXIT_FAILURE, "%s: resolved to multiple addresses", str); 2028 if (res->ai_addrlen != sizeof(struct sockaddr_in6)) 2029 errx(EXIT_FAILURE, "%s: bad value", str); 2030 memcpy(sin6, res->ai_addr, res->ai_addrlen); 2031 freeaddrinfo(res); 2032 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && sin6->sin6_scope_id) { 2033 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] = 2034 htons(sin6->sin6_scope_id); 2035 sin6->sin6_scope_id = 0; 2036 } 2037 if (slash) { 2038 in6_getprefix(slash + 1, MASK); 2039 explicit_prefix = 1; 2040 } 2041#else 2042 struct sockaddr_in6 *gasin = sin6tab[which]; 2043 2044 gasin->sin6_len = sizeof(*gasin); 2045 if (which != MASK) 2046 gasin->sin6_family = AF_INET6; 2047 2048 if (which == ADDR) { 2049 char *p = NULL; 2050 if((p = strrchr(str, '/')) != NULL) { 2051 *p = '\0'; 2052 in6_getprefix(p + 1, MASK); 2053 explicit_prefix = 1; 2054 } 2055 } 2056 2057 if (inet_pton(AF_INET6, str, &gasin->sin6_addr) != 1) 2058 errx(EXIT_FAILURE, "%s: bad value", str); 2059#endif 2060} 2061 2062void 2063in6_getprefix(const char *plen, int which) 2064{ 2065 struct sockaddr_in6 *gpsin = sin6tab[which]; 2066 u_char *cp; 2067 int len = strtol(plen, (char **)NULL, 10); 2068 2069 if ((len < 0) || (len > 128)) 2070 errx(EXIT_FAILURE, "%s: bad value", plen); 2071 gpsin->sin6_len = sizeof(*gpsin); 2072 if (which != MASK) 2073 gpsin->sin6_family = AF_INET6; 2074 if ((len == 0) || (len == 128)) { 2075 memset(&gpsin->sin6_addr, 0xff, sizeof(struct in6_addr)); 2076 return; 2077 } 2078 memset((void *)&gpsin->sin6_addr, 0x00, sizeof(gpsin->sin6_addr)); 2079 for (cp = (u_char *)&gpsin->sin6_addr; len > 7; len -= 8) 2080 *cp++ = 0xff; 2081 if (len) 2082 *cp = 0xff << (8 - len); 2083} 2084 2085int 2086prefix(void *val, int size) 2087{ 2088 u_char *pname = (u_char *)val; 2089 int byte, bit, plen = 0; 2090 2091 for (byte = 0; byte < size; byte++, plen += 8) 2092 if (pname[byte] != 0xff) 2093 break; 2094 if (byte == size) 2095 return (plen); 2096 for (bit = 7; bit != 0; bit--, plen++) 2097 if (!(pname[byte] & (1 << bit))) 2098 break; 2099 for (; bit != 0; bit--) 2100 if (pname[byte] & (1 << bit)) 2101 return(0); 2102 byte++; 2103 for (; byte < size; byte++) 2104 if (pname[byte]) 2105 return(0); 2106 return (plen); 2107} 2108#endif /*INET6*/ 2109 2110#ifndef INET_ONLY 2111#define SNS(x) ((struct sockaddr_ns *) &(x)) 2112struct sockaddr_ns *snstab[] = { 2113 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 2114 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 2115 2116void 2117xns_getaddr(const char *addr, int which) 2118{ 2119 struct sockaddr_ns *sns = snstab[which]; 2120 2121 sns->sns_family = AF_NS; 2122 sns->sns_len = sizeof(*sns); 2123 sns->sns_addr = ns_addr(addr); 2124 if (which == MASK) 2125 puts("Attempt to set XNS netmask will be ineffectual"); 2126} 2127 2128#define SISO(x) ((struct sockaddr_iso *) &(x)) 2129struct sockaddr_iso *sisotab[] = { 2130 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 2131 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 2132 2133void 2134iso_getaddr(const char *addr, int which) 2135{ 2136 struct sockaddr_iso *siso = sisotab[which]; 2137 siso->siso_addr = *iso_addr(addr); 2138 2139 if (which == MASK) { 2140 siso->siso_len = TSEL(siso) - (char *)(siso); 2141 siso->siso_nlen = 0; 2142 } else { 2143 siso->siso_len = sizeof(*siso); 2144 siso->siso_family = AF_ISO; 2145 } 2146} 2147 2148void 2149setsnpaoffset(const char *val, int d) 2150{ 2151 iso_addreq.ifra_snpaoffset = atoi(val); 2152} 2153 2154void 2155setnsellength(const char *val, int d) 2156{ 2157 nsellength = atoi(val); 2158 if (nsellength < 0) 2159 errx(EXIT_FAILURE, "Negative NSEL length is absurd"); 2160 if (afp == 0 || afp->af_af != AF_ISO) 2161 errx(EXIT_FAILURE, "Setting NSEL length valid only for iso"); 2162} 2163 2164void 2165fixnsel(struct sockaddr_iso *siso) 2166{ 2167 if (siso->siso_family == 0) 2168 return; 2169 siso->siso_tlen = nsellength; 2170} 2171 2172void 2173adjust_nsellength(void) 2174{ 2175 fixnsel(sisotab[RIDADDR]); 2176 fixnsel(sisotab[ADDR]); 2177 fixnsel(sisotab[DSTADDR]); 2178} 2179 2180#endif /* INET_ONLY */ 2181 2182void 2183usage(void) 2184{ 2185 const char *progname = getprogname(); 2186 2187 fprintf(stderr, 2188 "usage: %s [-m] [-v] [-z] " 2189#ifdef INET6 2190 "[-L] " 2191#endif 2192 "interface\n" 2193 "\t[ af [ address [ dest_addr ] ] [ netmask mask ] [ prefixlen n ]\n" 2194 "\t\t[ alias | -alias ] ]\n" 2195 "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n" 2196 "\t[ nwid network_id ] [ nwkey network_key | -nwkey ]\n" 2197 "\t[ powersave | -powersave ] [ powersavesleep duration ]\n" 2198 "\t[ [ af ] tunnel src_addr dest_addr ] [ deletetunnel ]\n" 2199 "\t[ arp | -arp ]\n" 2200 "\t[ media type ] [ mediaopt opts ] [ -mediaopt opts ] " 2201 "[ instance minst ]\n" 2202 "\t[ vlan n vlanif i ]\n" 2203 "\t[ agrport i ] [ -agrport i ]\n" 2204 "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n" 2205 "\t[ tentative | -tentative ] [ pltime n ] [ vltime n ] [ eui64 ]\n" 2206 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n" 2207 " %s -a [-b] [-m] [-d] [-u] [-v] [-z] [ af ]\n" 2208 " %s -l [-b] [-d] [-u] [-s]\n" 2209 " %s -C\n" 2210 " %s interface create\n" 2211 " %s interface destroy\n", 2212 progname, progname, progname, progname, progname, progname); 2213 exit(1); 2214} 2215 2216#ifdef INET6 2217char * 2218sec2str(total) 2219 time_t total; 2220{ 2221 static char result[256]; 2222 int days, hours, mins, secs; 2223 int first = 1; 2224 char *p = result; 2225 char *end = &result[sizeof(result)]; 2226 int n; 2227 2228 if (0) { /*XXX*/ 2229 days = total / 3600 / 24; 2230 hours = (total / 3600) % 24; 2231 mins = (total / 60) % 60; 2232 secs = total % 60; 2233 2234 if (days) { 2235 first = 0; 2236 n = snprintf(p, end - p, "%dd", days); 2237 if (n < 0 || n >= end - p) 2238 return(result); 2239 p += n; 2240 } 2241 if (!first || hours) { 2242 first = 0; 2243 n = snprintf(p, end - p, "%dh", hours); 2244 if (n < 0 || n >= end - p) 2245 return(result); 2246 p += n; 2247 } 2248 if (!first || mins) { 2249 first = 0; 2250 n = snprintf(p, end - p, "%dm", mins); 2251 if (n < 0 || n >= end - p) 2252 return(result); 2253 p += n; 2254 } 2255 snprintf(p, end - p, "%ds", secs); 2256 } else 2257 snprintf(p, end - p, "%lu", (u_long)total); 2258 2259 return(result); 2260} 2261#endif 2262