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