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