ifconfig.c revision 1.27
1/* $NetBSD: ifconfig.c,v 1.27 1997/03/18 05:04:50 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1997 Jason R. Thorpe. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Jason R. Thorpe. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35/* 36 * Copyright (c) 1983, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by the University of 50 * California, Berkeley and its contributors. 51 * 4. Neither the name of the University nor the names of its contributors 52 * may be used to endorse or promote products derived from this software 53 * without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 * SUCH DAMAGE. 66 */ 67 68#ifndef lint 69static char copyright[] = 70"@(#) Copyright (c) 1983, 1993\n\ 71 The Regents of the University of California. All rights reserved.\n"; 72#endif /* not lint */ 73 74#ifndef lint 75#if 0 76static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 77#else 78static char rcsid[] = "$NetBSD: ifconfig.c,v 1.27 1997/03/18 05:04:50 thorpej Exp $"; 79#endif 80#endif /* not lint */ 81 82#include <sys/param.h> 83#include <sys/socket.h> 84#include <sys/ioctl.h> 85 86#include <net/if.h> 87#include <net/if_media.h> 88#include <netinet/in.h> 89#include <arpa/inet.h> 90 91#define NSIP 92#include <netns/ns.h> 93#include <netns/ns_if.h> 94#include <netdb.h> 95 96#define EON 97#include <netiso/iso.h> 98#include <netiso/iso_var.h> 99#include <sys/protosw.h> 100 101#include <ctype.h> 102#include <err.h> 103#include <errno.h> 104#include <stdio.h> 105#include <stdlib.h> 106#include <string.h> 107#include <unistd.h> 108 109struct ifreq ifr, ridreq; 110struct ifaliasreq addreq; 111struct iso_aliasreq iso_addreq; 112struct sockaddr_in netmask; 113char name[30]; 114int flags, metric, setaddr, setipdst, doalias; 115int clearaddr, s; 116int newaddr = 1; 117int nsellength = 1; 118int af; 119int mflag; 120 121void notealias __P((char *, int)); 122void notrailers __P((char *, int)); 123void setifaddr __P((char *, int)); 124void setifdstaddr __P((char *, int)); 125void setifflags __P((char *, int)); 126void setifbroadaddr __P((char *)); 127void setifipdst __P((char *)); 128void setifmetric __P((char *)); 129void setifnetmask __P((char *)); 130void setnsellength __P((char *)); 131void setsnpaoffset __P((char *)); 132void setmedia __P((char *)); 133void setmediaopt __P((char *)); 134void unsetmediaopt __P((char *)); 135 136#define NEXTARG 0xffffff 137 138struct cmd { 139 char *c_name; 140 int c_parameter; /* NEXTARG means next argv */ 141 void (*c_func)(); 142} cmds[] = { 143 { "up", IFF_UP, setifflags } , 144 { "down", -IFF_UP, setifflags }, 145 { "trailers", -1, notrailers }, 146 { "-trailers", 1, notrailers }, 147 { "arp", -IFF_NOARP, setifflags }, 148 { "-arp", IFF_NOARP, setifflags }, 149 { "debug", IFF_DEBUG, setifflags }, 150 { "-debug", -IFF_DEBUG, setifflags }, 151 { "alias", IFF_UP, notealias }, 152 { "-alias", -IFF_UP, notealias }, 153 { "delete", -IFF_UP, notealias }, 154#ifdef notdef 155#define EN_SWABIPS 0x1000 156 { "swabips", EN_SWABIPS, setifflags }, 157 { "-swabips", -EN_SWABIPS, setifflags }, 158#endif 159 { "netmask", NEXTARG, setifnetmask }, 160 { "metric", NEXTARG, setifmetric }, 161 { "broadcast", NEXTARG, setifbroadaddr }, 162 { "ipdst", NEXTARG, setifipdst }, 163#ifndef INET_ONLY 164 { "snpaoffset", NEXTARG, setsnpaoffset }, 165 { "nsellength", NEXTARG, setnsellength }, 166#endif /* INET_ONLY */ 167 { "link0", IFF_LINK0, setifflags } , 168 { "-link0", -IFF_LINK0, setifflags } , 169 { "link1", IFF_LINK1, setifflags } , 170 { "-link1", -IFF_LINK1, setifflags } , 171 { "link2", IFF_LINK2, setifflags } , 172 { "-link2", -IFF_LINK2, setifflags } , 173 { "media", NEXTARG, setmedia }, 174 { "mediaopt", NEXTARG, setmediaopt }, 175 { "-mediaopt", NEXTARG, unsetmediaopt }, 176 { 0, 0, setifaddr }, 177 { 0, 0, setifdstaddr }, 178}; 179 180void adjust_nsellength(); 181int getinfo __P((struct ifreq *)); 182void getsock __P((int)); 183void printall __P((void)); 184void printb __P((char *, unsigned short, char *)); 185void status(); 186void usage(); 187 188void domediaopt __P((char *, int)); 189int get_media_subtype __P((int, char *)); 190int get_media_options __P((int, char *)); 191int lookup_media_word __P((struct ifmedia_description *, char *)); 192void print_media_word __P((int)); 193 194/* 195 * XNS support liberally adapted from code written at the University of 196 * Maryland principally by James O'Toole and Chris Torek. 197 */ 198void in_status __P((int)); 199void in_getaddr __P((char *, int)); 200void xns_status __P((int)); 201void xns_getaddr __P((char *, int)); 202void iso_status __P((int)); 203void iso_getaddr __P((char *, int)); 204 205/* Known address families */ 206struct afswtch { 207 char *af_name; 208 short af_af; 209 void (*af_status)(); 210 void (*af_getaddr)(); 211 u_long af_difaddr; 212 u_long af_aifaddr; 213 caddr_t af_ridreq; 214 caddr_t af_addreq; 215} afs[] = { 216#define C(x) ((caddr_t) &x) 217 { "inet", AF_INET, in_status, in_getaddr, 218 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 219#ifndef INET_ONLY /* small version, for boot media */ 220 { "ns", AF_NS, xns_status, xns_getaddr, 221 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 222 { "iso", AF_ISO, iso_status, iso_getaddr, 223 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(iso_addreq) }, 224#endif /* INET_ONLY */ 225 { 0, 0, 0, 0 } 226}; 227 228struct afswtch *afp; /*the address family being set or asked about*/ 229 230struct afswtch *lookup_af __P((const char *)); 231 232int 233main(argc, argv) 234 int argc; 235 char *argv[]; 236{ 237 extern int optind; 238 int ch, aflag; 239 240 /* Parse command-line options */ 241 aflag = mflag = 0; 242 while ((ch = getopt(argc, argv, "am")) != -1) { 243 switch (ch) { 244 case 'a': 245 aflag = 1; 246 break; 247 248 case 'm': 249 mflag = 1; 250 break; 251 252 default: 253 usage(); 254 /* NOTREACHED */ 255 } 256 } 257 argc -= optind; 258 argv += optind; 259 260 /* -a means print all interfaces */ 261 if (aflag) { 262 if (argc > 1) 263 usage(); 264 else if (argc == 1) { 265 afp = lookup_af(argv[0]); 266 if (afp == NULL) 267 usage(); 268 } else 269 afp = afs; 270 af = ifr.ifr_addr.sa_family = afp->af_af; 271 272 printall(); 273 exit(0); 274 } 275 276 /* Make sure there's an interface name. */ 277 if (argc < 1) 278 usage(); 279 strncpy(name, argv[0], sizeof(name)); 280 argc--; argv++; 281 282 /* Check for address family. */ 283 afp = NULL; 284 if (argc > 0) { 285 afp = lookup_af(argv[0]); 286 if (afp != NULL) { 287 argv++; 288 argc--; 289 } 290 } 291 292 if (afp == NULL) 293 afp = afs; 294 af = ifr.ifr_addr.sa_family = afp->af_af; 295 296 /* Get information about the interface. */ 297 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 298 if (getinfo(&ifr) < 0) 299 exit(1); 300 301 /* No more arguments means interface status. */ 302 if (argc == 0) { 303 status(); 304 exit(0); 305 } 306 307 /* Process commands. */ 308 while (argc > 0) { 309 register struct cmd *p; 310 311 for (p = cmds; p->c_name; p++) 312 if (strcmp(argv[0], p->c_name) == 0) 313 break; 314 if (p->c_name == 0 && setaddr) 315 p++; /* got src, do dst */ 316 if (p->c_func) { 317 if (p->c_parameter == NEXTARG) { 318 if (argc < 2) 319 errx(1, "'%s' requires argument", 320 p->c_name); 321 (*p->c_func)(argv[1]); 322 argc--, argv++; 323 } else 324 (*p->c_func)(argv[0], p->c_parameter); 325 } 326 argc--, argv++; 327 } 328 329#ifndef INET_ONLY 330 331 if (af == AF_ISO) 332 adjust_nsellength(); 333 if (setipdst && af==AF_NS) { 334 struct nsip_req rq; 335 int size = sizeof(rq); 336 337 rq.rq_ns = addreq.ifra_addr; 338 rq.rq_ip = addreq.ifra_dstaddr; 339 340 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 341 warn("encapsulation routing"); 342 } 343 344#endif /* INET_ONLY */ 345 346 if (clearaddr) { 347 int ret; 348 strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 349 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { 350 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 351 /* means no previous address for interface */ 352 } else 353 warn("SIOCDIFADDR"); 354 } 355 } 356 if (newaddr) { 357 strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 358 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 359 warn("SIOCAIFADDR"); 360 } 361 exit(0); 362} 363 364struct afswtch * 365lookup_af(cp) 366 const char *cp; 367{ 368 struct afswtch *a; 369 370 for (a = afs; a->af_name != NULL; a++) 371 if (strcmp(a->af_name, cp) == 0) 372 return (a); 373 return (NULL); 374} 375 376void 377getsock(naf) 378 int naf; 379{ 380 static int oaf = -1; 381 382 if (oaf == naf) 383 return; 384 if (oaf != -1) 385 close(s); 386 s = socket(naf, SOCK_DGRAM, 0); 387 if (s < 0) 388 oaf = -1; 389 else 390 oaf = naf; 391} 392 393int 394getinfo(ifr) 395 struct ifreq *ifr; 396{ 397 398 getsock(af); 399 if (s < 0) 400 err(1, "socket"); 401 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) { 402 warn("SIOCGIFFLAGS"); 403 return (-1); 404 } 405 flags = ifr->ifr_flags; 406 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) { 407 warn("SIOCGIFMETRIC"); 408 metric = 0; 409 } else 410 metric = ifr->ifr_metric; 411 return (0); 412} 413 414void 415printall() 416{ 417 char inbuf[8192]; 418 struct ifconf ifc; 419 struct ifreq ifreq, *ifr; 420 int i; 421 422 ifc.ifc_len = sizeof(inbuf); 423 ifc.ifc_buf = inbuf; 424 getsock(af); 425 if (s < 0) 426 err(1, "socket"); 427 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) 428 err(1, "SIOCGIFCONF"); 429 ifr = ifc.ifc_req; 430 ifreq.ifr_name[0] = '\0'; 431 for (i = 0; i < ifc.ifc_len; ) { 432 ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i); 433 i += sizeof(ifr->ifr_name) + 434 (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) 435 ? ifr->ifr_addr.sa_len 436 : sizeof(struct sockaddr)); 437 if (!strncmp(ifreq.ifr_name, ifr->ifr_name, 438 sizeof(ifr->ifr_name))) 439 continue; 440 strncpy(name, ifr->ifr_name, sizeof(ifr->ifr_name)); 441 ifreq = *ifr; 442 if (getinfo(&ifreq) < 0) 443 continue; 444 status(); 445 } 446} 447 448#define RIDADDR 0 449#define ADDR 1 450#define MASK 2 451#define DSTADDR 3 452 453/*ARGSUSED*/ 454void 455setifaddr(addr, param) 456 char *addr; 457 int param; 458{ 459 /* 460 * Delay the ioctl to set the interface addr until flags are all set. 461 * The address interpretation may depend on the flags, 462 * and the flags may change when the address is set. 463 */ 464 setaddr++; 465 if (doalias == 0) 466 clearaddr = 1; 467 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 468} 469 470void 471setifnetmask(addr) 472 char *addr; 473{ 474 (*afp->af_getaddr)(addr, MASK); 475} 476 477void 478setifbroadaddr(addr) 479 char *addr; 480{ 481 (*afp->af_getaddr)(addr, DSTADDR); 482} 483 484void 485setifipdst(addr) 486 char *addr; 487{ 488 in_getaddr(addr, DSTADDR); 489 setipdst++; 490 clearaddr = 0; 491 newaddr = 0; 492} 493 494#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 495/*ARGSUSED*/ 496void 497notealias(addr, param) 498 char *addr; 499 int param; 500{ 501 if (setaddr && doalias == 0 && param < 0) 502 memcpy(rqtosa(af_ridreq), 503 rqtosa(af_addreq), 504 rqtosa(af_addreq)->sa_len); 505 doalias = param; 506 if (param < 0) { 507 clearaddr = 1; 508 newaddr = 0; 509 } else 510 clearaddr = 0; 511} 512 513/*ARGSUSED*/ 514void 515notrailers(vname, value) 516 char *vname; 517 int value; 518{ 519 printf("Note: trailers are no longer sent, but always received\n"); 520} 521 522/*ARGSUSED*/ 523void 524setifdstaddr(addr, param) 525 char *addr; 526 int param; 527{ 528 (*afp->af_getaddr)(addr, DSTADDR); 529} 530 531void 532setifflags(vname, value) 533 char *vname; 534 int value; 535{ 536 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) 537 err(1, "SIOCGIFFLAGS"); 538 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 539 flags = ifr.ifr_flags; 540 541 if (value < 0) { 542 value = -value; 543 flags &= ~value; 544 } else 545 flags |= value; 546 ifr.ifr_flags = flags; 547 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 548 err(1, "SIOCSIFFLAGS"); 549} 550 551void 552setifmetric(val) 553 char *val; 554{ 555 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 556 ifr.ifr_metric = atoi(val); 557 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 558 warn("SIOCSIFMETRIC"); 559} 560 561void 562setmedia(val) 563 char *val; 564{ 565 struct ifmediareq ifmr; 566 int first_type, subtype; 567 568 memset(&ifmr, 0, sizeof(ifmr)); 569 strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 570 571 ifmr.ifm_count = 1; 572 ifmr.ifm_ulist = &first_type; 573 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 574 /* 575 * If we get E2BIG, the kernel is telling us 576 * that there are more, so we can ignore it. 577 */ 578 if (errno != E2BIG) 579 err(1, "SIOCGIFMEDIA"); 580 } 581 582 if (ifmr.ifm_count == 0) 583 errx(1, "%s: no media types?", name); 584 585 /* 586 * We are primarily concerned with the top-level type. 587 * However, "current" may be only IFM_NONE, so we just look 588 * for the top-level type in the first "supported type" 589 * entry. 590 * 591 * (I'm assuming that all supported media types for a given 592 * interface will be the same top-level type..) 593 */ 594 subtype = get_media_subtype(IFM_TYPE(first_type), val); 595 596 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 597 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 598 IFM_TYPE(first_type) | subtype; 599 600 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 601 err(1, "SIOCSIFMEDIA"); 602} 603 604void 605setmediaopt(val) 606 char *val; 607{ 608 609 domediaopt(val, 0); 610} 611 612void 613unsetmediaopt(val) 614 char *val; 615{ 616 617 domediaopt(val, 1); 618} 619 620void 621domediaopt(val, clear) 622 char *val; 623 int clear; 624{ 625 struct ifmediareq ifmr; 626 int *mwords, options; 627 628 memset(&ifmr, 0, sizeof(ifmr)); 629 strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 630 631 /* 632 * We must go through the motions of reading all 633 * supported media because we need to know both 634 * the current media type and the top-level type. 635 */ 636 637 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 638 err(1, "SIOCGIFMEDIA"); 639 640 if (ifmr.ifm_count == 0) 641 errx(1, "%s: no media types?", name); 642 643 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int)); 644 if (mwords == NULL) 645 err(1, "malloc"); 646 647 ifmr.ifm_ulist = mwords; 648 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 649 err(1, "SIOCGIFMEDIA"); 650 651 options = get_media_options(IFM_TYPE(mwords[0]), val); 652 653 free(mwords); 654 655 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 656 ifr.ifr_media = ifmr.ifm_current; 657 if (clear) 658 ifr.ifr_media &= ~options; 659 else 660 ifr.ifr_media |= options; 661 662 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 663 err(1, "SIOCSIFMEDIA"); 664} 665 666/********************************************************************** 667 * A good chunk of this is duplicated from sys/net/ifmedia.c 668 **********************************************************************/ 669 670struct ifmedia_description ifm_type_descriptions[] = 671 IFM_TYPE_DESCRIPTIONS; 672 673struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 674 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 675 676struct ifmedia_description ifm_subtype_ethernet_aliases[] = 677 IFM_SUBTYPE_ETHERNET_ALIASES; 678 679struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 680 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 681 682struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 683 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 684 685struct ifmedia_description ifm_subtype_tokenring_aliases[] = 686 IFM_SUBTYPE_TOKENRING_ALIASES; 687 688struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 689 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 690 691struct ifmedia_description ifm_subtype_fddi_descriptions[] = 692 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 693 694struct ifmedia_description ifm_subtype_fddi_aliases[] = 695 IFM_SUBTYPE_FDDI_ALIASES; 696 697struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 698 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 699 700struct ifmedia_description ifm_subtype_shared_descriptions[] = 701 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 702 703struct ifmedia_description ifm_subtype_shared_aliases[] = 704 IFM_SUBTYPE_SHARED_ALIASES; 705 706struct ifmedia_description ifm_shared_option_descriptions[] = 707 IFM_SHARED_OPTION_DESCRIPTIONS; 708 709struct ifmedia_type_to_subtype { 710 struct { 711 struct ifmedia_description *desc; 712 int alias; 713 } subtypes[5]; 714 struct { 715 struct ifmedia_description *desc; 716 int alias; 717 } options[3]; 718}; 719 720/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 721struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 722 { 723 { 724 { &ifm_subtype_shared_descriptions[0], 0 }, 725 { &ifm_subtype_shared_aliases[0], 1 }, 726 { &ifm_subtype_ethernet_descriptions[0], 0 }, 727 { &ifm_subtype_ethernet_aliases[0], 1 }, 728 { NULL, 0 }, 729 }, 730 { 731 { &ifm_shared_option_descriptions[0], 0 }, 732 { &ifm_subtype_ethernet_option_descriptions[0], 1 }, 733 { NULL, 0 }, 734 }, 735 }, 736 { 737 { 738 { &ifm_subtype_shared_descriptions[0], 0 }, 739 { &ifm_subtype_shared_aliases[0], 1 }, 740 { &ifm_subtype_tokenring_descriptions[0], 0 }, 741 { &ifm_subtype_tokenring_aliases[0], 1 }, 742 { NULL, 0 }, 743 }, 744 { 745 { &ifm_shared_option_descriptions[0], 0 }, 746 { &ifm_subtype_tokenring_option_descriptions[0], 1 }, 747 { NULL, 0 }, 748 }, 749 }, 750 { 751 { 752 { &ifm_subtype_shared_descriptions[0], 0 }, 753 { &ifm_subtype_shared_aliases[0], 1 }, 754 { &ifm_subtype_fddi_descriptions[0], 0 }, 755 { &ifm_subtype_fddi_aliases[0], 1 }, 756 { NULL, 0 }, 757 }, 758 { 759 { &ifm_shared_option_descriptions[0], 0 }, 760 { &ifm_subtype_fddi_option_descriptions[0], 1 }, 761 { NULL, 0 }, 762 }, 763 }, 764}; 765 766int 767get_media_subtype(type, val) 768 int type; 769 char *val; 770{ 771 struct ifmedia_description *desc; 772 struct ifmedia_type_to_subtype *ttos; 773 int rval, i; 774 775 /* Find the top-level interface type. */ 776 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 777 desc->ifmt_string != NULL; desc++, ttos++) 778 if (type == desc->ifmt_word) 779 break; 780 if (desc->ifmt_string == NULL) 781 errx(1, "unknown media type 0x%x", type); 782 783 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 784 rval = lookup_media_word(ttos->subtypes[i].desc, val); 785 if (rval != -1) 786 return (rval); 787 } 788 errx(1, "unknown media subtype: %s", val); 789 /* NOTREACHED */ 790} 791 792int 793get_media_options(type, val) 794 int type; 795 char *val; 796{ 797 struct ifmedia_description *desc; 798 struct ifmedia_type_to_subtype *ttos; 799 char *optlist; 800 int option, i, rval = 0; 801 802 /* We muck with the string, so copy it. */ 803 optlist = strdup(val); 804 if (optlist == NULL) 805 err(1, "strdup"); 806 val = optlist; 807 808 /* Find the top-level interface type. */ 809 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 810 desc->ifmt_string != NULL; desc++, ttos++) 811 if (type == desc->ifmt_word) 812 break; 813 if (desc->ifmt_string == NULL) 814 errx(1, "unknown media type 0x%x", type); 815 816 /* 817 * Look up the options in the user-provided comma-separated 818 * list. 819 */ 820 for (; (val = strtok(val, ",")) != NULL; val = NULL) { 821 for (i = 0; ttos->options[i].desc != NULL; i++) { 822 option = lookup_media_word(ttos->options[i].desc, val); 823 if (option != -1) 824 break; 825 } 826 if (option == 0) 827 errx(1, "unknown option: %s", val); 828 rval |= option; 829 } 830 831 free(optlist); 832 return (rval); 833} 834 835int 836lookup_media_word(desc, val) 837 struct ifmedia_description *desc; 838 char *val; 839{ 840 841 for (; desc->ifmt_string != NULL; desc++) 842 if (strcasecmp(desc->ifmt_string, val) == 0) 843 return (desc->ifmt_word); 844 845 return (-1); 846} 847 848void 849print_media_word(ifmw) 850 int ifmw; 851{ 852 struct ifmedia_description *desc; 853 struct ifmedia_type_to_subtype *ttos; 854 int seen_option = 0, i; 855 856 /* Find the top-level interface type. */ 857 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 858 desc->ifmt_string != NULL; desc++, ttos++) 859 if (IFM_TYPE(ifmw) == desc->ifmt_word) 860 break; 861 if (desc->ifmt_string == NULL) { 862 printf("<unknown type>"); 863 return; 864 } 865 866 /* 867 * Don't print the top-level type; it's not like we can 868 * change it, or anything. 869 */ 870 871 /* Find subtype. */ 872 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 873 if (ttos->subtypes[i].alias) 874 continue; 875 for (desc = ttos->subtypes[i].desc; 876 desc->ifmt_string != NULL; desc++) { 877 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 878 goto got_subtype; 879 } 880 } 881 882 /* Falling to here means unknown subtype. */ 883 printf("<unknown subtype>"); 884 return; 885 886 got_subtype: 887 printf("%s", desc->ifmt_string); 888 889 /* Find options. */ 890 for (i = 0; ttos->options[i].desc != NULL; i++) { 891 if (ttos->options[i].alias) 892 continue; 893 for (desc = ttos->options[i].desc; 894 desc->ifmt_string != NULL; desc++) { 895 if (ifmw & desc->ifmt_word) { 896 if (seen_option == 0) 897 printf(" <"); 898 printf("%s%s", seen_option++ ? "," : "", 899 desc->ifmt_string); 900 } 901 } 902 } 903 printf("%s", seen_option ? ">" : ""); 904} 905 906/********************************************************************** 907 * ...until here. 908 **********************************************************************/ 909 910#define IFFBITS \ 911"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 912\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 913 914/* 915 * Print the status of the interface. If an address family was 916 * specified, show it and it only; otherwise, show them all. 917 */ 918void 919status() 920{ 921 register struct afswtch *p = afp; 922 struct ifmediareq ifmr; 923 int *media_list, i; 924 925 printf("%s: ", name); 926 printb("flags", flags, IFFBITS); 927 if (metric) 928 printf(" metric %d", metric); 929 putchar('\n'); 930 931 memset(&ifmr, 0, sizeof(ifmr)); 932 strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 933 934 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 935 /* 936 * Interface doesn't support SIOC{G,S}IFMEDIA. 937 */ 938 goto proto_status; 939 } 940 941 if (ifmr.ifm_count == 0) { 942 warnx("%s: no media types?", ifr.ifr_name); 943 goto proto_status; 944 } 945 946 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 947 if (media_list == NULL) 948 err(1, "malloc"); 949 ifmr.ifm_ulist = media_list; 950 951 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 952 err(1, "SIOCGIFMEDIA"); 953 954 printf("\tmedia: "); 955 print_media_word(ifmr.ifm_current); 956 if (ifmr.ifm_active != ifmr.ifm_current) { 957 putchar('('); 958 print_media_word(ifmr.ifm_current); 959 putchar(')'); 960 } 961 962 if (ifmr.ifm_status & IFM_AVALID) { 963 printf(" status: "); 964 switch (IFM_TYPE(ifmr.ifm_active)) { 965 case IFM_ETHER: 966 if (ifmr.ifm_status & IFM_ACTIVE) 967 printf("active"); 968 else 969 printf("no carrier"); 970 break; 971 972 case IFM_FDDI: 973 case IFM_TOKEN: 974 if (ifmr.ifm_status & IFM_ACTIVE) 975 printf("inserted"); 976 else 977 printf("no ring"); 978 break; 979 } 980 } 981 982 putchar('\n'); 983 984 if (mflag) { 985 printf("\tsupported media:"); 986 for (i = 0; i < ifmr.ifm_count; i++) { 987 putchar(' '); 988 print_media_word(media_list[i]); 989 } 990 putchar('\n'); 991 } 992 993 free(media_list); 994 995 proto_status: 996 if ((p = afp) != NULL) { 997 (*p->af_status)(1); 998 } else for (p = afs; p->af_name; p++) { 999 ifr.ifr_addr.sa_family = p->af_af; 1000 (*p->af_status)(0); 1001 } 1002} 1003 1004void 1005in_status(force) 1006 int force; 1007{ 1008 struct sockaddr_in *sin; 1009 char *inet_ntoa(); 1010 1011 getsock(AF_INET); 1012 if (s < 0) { 1013 if (errno == EPROTONOSUPPORT) 1014 return; 1015 err(1, "socket"); 1016 } 1017 memset(&ifr, 0, sizeof(ifr)); 1018 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1019 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1020 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1021 if (!force) 1022 return; 1023 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1024 } else 1025 warn("SIOCGIFADDR"); 1026 } 1027 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1028 sin = (struct sockaddr_in *)&ifr.ifr_addr; 1029 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 1030 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1031 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 1032 if (errno != EADDRNOTAVAIL) 1033 warn("SIOCGIFNETMASK"); 1034 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1035 } else 1036 netmask.sin_addr = 1037 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 1038 if (flags & IFF_POINTOPOINT) { 1039 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1040 if (errno == EADDRNOTAVAIL) 1041 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1042 else 1043 warn("SIOCGIFDSTADDR"); 1044 } 1045 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1046 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 1047 printf("--> %s ", inet_ntoa(sin->sin_addr)); 1048 } 1049 printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr)); 1050 if (flags & IFF_BROADCAST) { 1051 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 1052 if (errno == EADDRNOTAVAIL) 1053 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1054 else 1055 warn("SIOCGIFBRDADDR"); 1056 } 1057 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1058 sin = (struct sockaddr_in *)&ifr.ifr_addr; 1059 if (sin->sin_addr.s_addr != 0) 1060 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 1061 } 1062 putchar('\n'); 1063} 1064 1065#ifndef INET_ONLY 1066 1067void 1068xns_status(force) 1069 int force; 1070{ 1071 struct sockaddr_ns *sns; 1072 1073 getsock(AF_NS); 1074 if (s < 0) { 1075 if (errno == EPROTONOSUPPORT) 1076 return; 1077 err(1, "socket"); 1078 } 1079 memset(&ifr, 0, sizeof(ifr)); 1080 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1081 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1082 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1083 if (!force) 1084 return; 1085 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1086 } else 1087 warn("SIOCGIFADDR"); 1088 } 1089 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 1090 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 1091 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1092 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 1093 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1094 if (errno == EADDRNOTAVAIL) 1095 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1096 else 1097 warn("SIOCGIFDSTADDR"); 1098 } 1099 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1100 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 1101 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1102 } 1103 putchar('\n'); 1104} 1105 1106void 1107iso_status(force) 1108 int force; 1109{ 1110 struct sockaddr_iso *siso; 1111 1112 getsock(AF_ISO); 1113 if (s < 0) { 1114 if (errno == EPROTONOSUPPORT) 1115 return; 1116 err(1, "socket"); 1117 } 1118 memset(&ifr, 0, sizeof(ifr)); 1119 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1120 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1121 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1122 if (!force) 1123 return; 1124 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1125 } else 1126 warn("SIOCGIFADDR"); 1127 } 1128 strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 1129 siso = (struct sockaddr_iso *)&ifr.ifr_addr; 1130 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 1131 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 1132 if (errno == EADDRNOTAVAIL) 1133 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1134 else 1135 warn("SIOCGIFNETMASK"); 1136 } else { 1137 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 1138 } 1139 if (flags & IFF_POINTOPOINT) { 1140 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1141 if (errno == EADDRNOTAVAIL) 1142 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1143 else 1144 warn("SIOCGIFDSTADDR"); 1145 } 1146 strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1147 siso = (struct sockaddr_iso *)&ifr.ifr_addr; 1148 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 1149 } 1150 putchar('\n'); 1151} 1152 1153#endif /* INET_ONLY */ 1154 1155struct in_addr inet_makeaddr(); 1156 1157#define SIN(x) ((struct sockaddr_in *) &(x)) 1158struct sockaddr_in *sintab[] = { 1159SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1160SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1161 1162void 1163in_getaddr(s, which) 1164 char *s; 1165 int which; 1166{ 1167 register struct sockaddr_in *sin = sintab[which]; 1168 struct hostent *hp; 1169 struct netent *np; 1170 1171 sin->sin_len = sizeof(*sin); 1172 if (which != MASK) 1173 sin->sin_family = AF_INET; 1174 1175 if (inet_aton(s, &sin->sin_addr) == 0) { 1176 if (hp = gethostbyname(s)) 1177 memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); 1178 else if (np = getnetbyname(s)) 1179 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1180 else 1181 errx(1, "%s: bad value", s); 1182 } 1183} 1184 1185/* 1186 * Print a value a la the %b format of the kernel's printf 1187 */ 1188void 1189printb(s, v, bits) 1190 char *s; 1191 register char *bits; 1192 register unsigned short v; 1193{ 1194 register int i, any = 0; 1195 register char c; 1196 1197 if (bits && *bits == 8) 1198 printf("%s=%o", s, v); 1199 else 1200 printf("%s=%x", s, v); 1201 bits++; 1202 if (bits) { 1203 putchar('<'); 1204 while (i = *bits++) { 1205 if (v & (1 << (i-1))) { 1206 if (any) 1207 putchar(','); 1208 any = 1; 1209 for (; (c = *bits) > 32; bits++) 1210 putchar(c); 1211 } else 1212 for (; *bits > 32; bits++) 1213 ; 1214 } 1215 putchar('>'); 1216 } 1217} 1218 1219#ifndef INET_ONLY 1220 1221#define SNS(x) ((struct sockaddr_ns *) &(x)) 1222struct sockaddr_ns *snstab[] = { 1223SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 1224SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 1225 1226void 1227xns_getaddr(addr, which) 1228 char *addr; 1229 int which; 1230{ 1231 struct sockaddr_ns *sns = snstab[which]; 1232 struct ns_addr ns_addr(); 1233 1234 sns->sns_family = AF_NS; 1235 sns->sns_len = sizeof(*sns); 1236 sns->sns_addr = ns_addr(addr); 1237 if (which == MASK) 1238 printf("Attempt to set XNS netmask will be ineffectual\n"); 1239} 1240 1241#define SISO(x) ((struct sockaddr_iso *) &(x)) 1242struct sockaddr_iso *sisotab[] = { 1243SISO(ridreq.ifr_addr), SISO(iso_addreq.ifra_addr), 1244SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 1245 1246void 1247iso_getaddr(addr, which) 1248 char *addr; 1249 int which; 1250{ 1251 register struct sockaddr_iso *siso = sisotab[which]; 1252 struct iso_addr *iso_addr(); 1253 siso->siso_addr = *iso_addr(addr); 1254 1255 if (which == MASK) { 1256 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 1257 siso->siso_nlen = 0; 1258 } else { 1259 siso->siso_len = sizeof(*siso); 1260 siso->siso_family = AF_ISO; 1261 } 1262} 1263 1264void 1265setsnpaoffset(val) 1266 char *val; 1267{ 1268 iso_addreq.ifra_snpaoffset = atoi(val); 1269} 1270 1271void 1272setnsellength(val) 1273 char *val; 1274{ 1275 nsellength = atoi(val); 1276 if (nsellength < 0) 1277 errx(1, "Negative NSEL length is absurd"); 1278 if (afp == 0 || afp->af_af != AF_ISO) 1279 errx(1, "Setting NSEL length valid only for iso"); 1280} 1281 1282void 1283fixnsel(s) 1284 register struct sockaddr_iso *s; 1285{ 1286 if (s->siso_family == 0) 1287 return; 1288 s->siso_tlen = nsellength; 1289} 1290 1291void 1292adjust_nsellength() 1293{ 1294 fixnsel(sisotab[RIDADDR]); 1295 fixnsel(sisotab[ADDR]); 1296 fixnsel(sisotab[DSTADDR]); 1297} 1298 1299#endif /* INET_ONLY */ 1300 1301void 1302usage() 1303{ 1304 fprintf(stderr, "usage: ifconfig [ -m ] interface\n%s%s%s%s%s%s%s%s%s", 1305 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ] ", 1306 "[ netmask mask ] ]\n", 1307 "\t[ metric n ]\n", 1308 "\t[ arp | -arp ]\n", 1309 "\t[ media mtype ]\n", 1310 "\t[ mediaopt mopts ]\n", 1311 "\t[ -mediaopt mopts ]\n", 1312 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n", 1313 " ifconfig -a [ -m ] [ af ]\n"); 1314 exit(1); 1315} 1316