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