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