ifconfig.c revision 1.36
1/* $NetBSD: ifconfig.c,v 1.36 1997/05/30 05:44:11 lukem 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.36 1997/05/30 05:44:11 lukem 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_dl.h> 88#include <net/if_media.h> 89#include <netinet/in.h> 90#include <arpa/inet.h> 91 92#include <netatalk/at.h> 93 94#define NSIP 95#include <netns/ns.h> 96#include <netns/ns_if.h> 97#include <netdb.h> 98 99#define EON 100#include <netiso/iso.h> 101#include <netiso/iso_var.h> 102#include <sys/protosw.h> 103 104#include <ctype.h> 105#include <err.h> 106#include <errno.h> 107#include <stdio.h> 108#include <stdlib.h> 109#include <string.h> 110#include <unistd.h> 111 112struct ifreq ifr, ridreq; 113struct ifaliasreq addreq __attribute__((aligned(4))); 114struct iso_aliasreq iso_addreq; 115struct sockaddr_in netmask; 116struct netrange at_nr; /* AppleTalk net range */ 117 118char name[30]; 119int flags, metric, mtu, setaddr, setipdst, doalias; 120int clearaddr, s; 121int newaddr = -1; 122int nsellength = 1; 123int af; 124int dflag, mflag, lflag, uflag; 125 126void notealias __P((char *, int)); 127void notrailers __P((char *, int)); 128void setifaddr __P((char *, int)); 129void setifdstaddr __P((char *, int)); 130void setifflags __P((char *, int)); 131void setifbroadaddr __P((char *, int)); 132void setifipdst __P((char *, int)); 133void setifmetric __P((char *, int)); 134void setifmtu __P((char *, int)); 135void setifnetmask __P((char *, int)); 136void setnsellength __P((char *, int)); 137void setsnpaoffset __P((char *, int)); 138void setatrange __P((char *, int)); 139void setatphase __P((char *, int)); 140void checkatrange __P ((struct sockaddr_at *)); 141void setmedia __P((char *, int)); 142void setmediaopt __P((char *, int)); 143void unsetmediaopt __P((char *, int)); 144void fixnsel __P((struct sockaddr_iso *)); 145int main __P((int, char *[])); 146 147#define NEXTARG 0xffffff 148 149struct cmd { 150 char *c_name; 151 int c_parameter; /* NEXTARG means next argv */ 152 void (*c_func) __P((char *, int)); 153} cmds[] = { 154 { "up", IFF_UP, setifflags } , 155 { "down", -IFF_UP, setifflags }, 156 { "trailers", -1, notrailers }, 157 { "-trailers", 1, notrailers }, 158 { "arp", -IFF_NOARP, setifflags }, 159 { "-arp", IFF_NOARP, setifflags }, 160 { "debug", IFF_DEBUG, setifflags }, 161 { "-debug", -IFF_DEBUG, setifflags }, 162 { "alias", IFF_UP, notealias }, 163 { "-alias", -IFF_UP, notealias }, 164 { "delete", -IFF_UP, notealias }, 165#ifdef notdef 166#define EN_SWABIPS 0x1000 167 { "swabips", EN_SWABIPS, setifflags }, 168 { "-swabips", -EN_SWABIPS, setifflags }, 169#endif 170 { "netmask", NEXTARG, setifnetmask }, 171 { "metric", NEXTARG, setifmetric }, 172 { "mtu", NEXTARG, setifmtu }, 173 { "broadcast", NEXTARG, setifbroadaddr }, 174 { "ipdst", NEXTARG, setifipdst }, 175#ifndef INET_ONLY 176 { "range", NEXTARG, setatrange }, 177 { "phase", NEXTARG, setatphase }, 178 { "snpaoffset", NEXTARG, setsnpaoffset }, 179 { "nsellength", NEXTARG, setnsellength }, 180#endif /* INET_ONLY */ 181 { "link0", IFF_LINK0, setifflags } , 182 { "-link0", -IFF_LINK0, setifflags } , 183 { "link1", IFF_LINK1, setifflags } , 184 { "-link1", -IFF_LINK1, setifflags } , 185 { "link2", IFF_LINK2, setifflags } , 186 { "-link2", -IFF_LINK2, setifflags } , 187 { "media", NEXTARG, setmedia }, 188 { "mediaopt", NEXTARG, setmediaopt }, 189 { "-mediaopt", NEXTARG, unsetmediaopt }, 190 { 0, 0, setifaddr }, 191 { 0, 0, setifdstaddr }, 192}; 193 194void adjust_nsellength __P((void)); 195int getinfo __P((struct ifreq *)); 196void getsock __P((int)); 197void printall __P((void)); 198void printb __P((char *, unsigned short, char *)); 199void status __P((const u_int8_t *, int)); 200void usage __P((void)); 201 202void domediaopt __P((char *, int)); 203int get_media_subtype __P((int, char *)); 204int get_media_options __P((int, char *)); 205int lookup_media_word __P((struct ifmedia_description *, char *)); 206void print_media_word __P((int)); 207 208/* 209 * XNS support liberally adapted from code written at the University of 210 * Maryland principally by James O'Toole and Chris Torek. 211 */ 212void in_status __P((int)); 213void in_getaddr __P((char *, int)); 214void at_status __P((int)); 215void at_getaddr __P((char *, int)); 216void xns_status __P((int)); 217void xns_getaddr __P((char *, int)); 218void iso_status __P((int)); 219void iso_getaddr __P((char *, int)); 220 221/* Known address families */ 222struct afswtch { 223 char *af_name; 224 short af_af; 225 void (*af_status) __P((int)); 226 void (*af_getaddr) __P((char *, int)); 227 u_long af_difaddr; 228 u_long af_aifaddr; 229 caddr_t af_ridreq; 230 caddr_t af_addreq; 231} afs[] = { 232#define C(x) ((caddr_t) &x) 233 { "inet", AF_INET, in_status, in_getaddr, 234 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 235#ifndef INET_ONLY /* small version, for boot media */ 236 { "atalk", AF_APPLETALK, at_status, at_getaddr, 237 SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) }, 238 { "ns", AF_NS, xns_status, xns_getaddr, 239 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 240 { "iso", AF_ISO, iso_status, iso_getaddr, 241 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(iso_addreq) }, 242#endif /* INET_ONLY */ 243 { 0, 0, 0, 0 } 244}; 245 246struct afswtch *afp; /*the address family being set or asked about*/ 247 248struct afswtch *lookup_af __P((const char *)); 249 250int 251main(argc, argv) 252 int argc; 253 char *argv[]; 254{ 255 extern int optind; 256 int ch, aflag; 257 258 /* Parse command-line options */ 259 aflag = mflag = 0; 260 while ((ch = getopt(argc, argv, "adlmu")) != -1) { 261 switch (ch) { 262 case 'a': 263 aflag = 1; 264 break; 265 266 case 'd': 267 dflag = 1; 268 break; 269 270 case 'l': 271 lflag = 1; 272 break; 273 274 case 'm': 275 mflag = 1; 276 break; 277 278 case 'u': 279 uflag = 1; 280 break; 281 282 default: 283 usage(); 284 /* NOTREACHED */ 285 } 286 } 287 argc -= optind; 288 argv += optind; 289 290 /* 291 * -l means "list all interfaces", and is mutally exclusive with 292 * all other flags/commands. 293 * 294 * -a means "print status of all interfaces". 295 */ 296 if (lflag && (aflag || mflag || argc)) 297 usage(); 298 if (aflag || lflag) { 299 if (argc > 1) 300 usage(); 301 else if (argc == 1) { 302 afp = lookup_af(argv[0]); 303 if (afp == NULL) 304 usage(); 305 } 306 if (afp) 307 af = ifr.ifr_addr.sa_family = afp->af_af; 308 else 309 af = ifr.ifr_addr.sa_family = afs[0].af_af; 310 printall(); 311 exit(0); 312 } 313 314 /* Make sure there's an interface name. */ 315 if (argc < 1) 316 usage(); 317 (void) strncpy(name, argv[0], sizeof(name)); 318 argc--; argv++; 319 320 /* Check for address family. */ 321 afp = NULL; 322 if (argc > 0) { 323 afp = lookup_af(argv[0]); 324 if (afp != NULL) { 325 argv++; 326 argc--; 327 } 328 } 329 330 if (afp == NULL) 331 afp = afs; 332 af = ifr.ifr_addr.sa_family = afp->af_af; 333 334 /* Get information about the interface. */ 335 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 336 if (getinfo(&ifr) < 0) 337 exit(1); 338 339 /* No more arguments means interface status. */ 340 if (argc == 0) { 341 status(NULL, 0); 342 exit(0); 343 } 344 345 /* Process commands. */ 346 while (argc > 0) { 347 register struct cmd *p; 348 349 for (p = cmds; p->c_name; p++) 350 if (strcmp(argv[0], p->c_name) == 0) 351 break; 352 if (p->c_name == 0 && setaddr) 353 p++; /* got src, do dst */ 354 if (p->c_func) { 355 if (p->c_parameter == NEXTARG) { 356 if (argc < 2) 357 errx(1, "'%s' requires argument", 358 p->c_name); 359 (*p->c_func)(argv[1], 0); 360 argc--, argv++; 361 } else 362 (*p->c_func)(argv[0], p->c_parameter); 363 } 364 argc--, argv++; 365 } 366 367#ifndef INET_ONLY 368 369 if (af == AF_ISO) 370 adjust_nsellength(); 371 372 if (af == AF_APPLETALK) 373 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 374 375 if (setipdst && af==AF_NS) { 376 struct nsip_req rq; 377 int size = sizeof(rq); 378 379 rq.rq_ns = addreq.ifra_addr; 380 rq.rq_ip = addreq.ifra_dstaddr; 381 382 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 383 warn("encapsulation routing"); 384 } 385 386#endif /* INET_ONLY */ 387 388 if (clearaddr) { 389 int ret; 390 (void) strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 391 if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { 392 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 393 /* means no previous address for interface */ 394 } else 395 warn("SIOCDIFADDR"); 396 } 397 } 398 if (newaddr > 0) { 399 (void) strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 400 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 401 warn("SIOCAIFADDR"); 402 } 403 exit(0); 404} 405 406struct afswtch * 407lookup_af(cp) 408 const char *cp; 409{ 410 struct afswtch *a; 411 412 for (a = afs; a->af_name != NULL; a++) 413 if (strcmp(a->af_name, cp) == 0) 414 return (a); 415 return (NULL); 416} 417 418void 419getsock(naf) 420 int naf; 421{ 422 static int oaf = -1; 423 424 if (oaf == naf) 425 return; 426 if (oaf != -1) 427 close(s); 428 s = socket(naf, SOCK_DGRAM, 0); 429 if (s < 0) 430 oaf = -1; 431 else 432 oaf = naf; 433} 434 435int 436getinfo(ifr) 437 struct ifreq *ifr; 438{ 439 440 getsock(af); 441 if (s < 0) 442 err(1, "socket"); 443 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) { 444 warn("SIOCGIFFLAGS %s", ifr->ifr_name); 445 return (-1); 446 } 447 flags = ifr->ifr_flags; 448 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) { 449 warn("SIOCGIFMETRIC %s", ifr->ifr_name); 450 metric = 0; 451 } else 452 metric = ifr->ifr_metric; 453 if (ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) 454 mtu = 0; 455 else 456 mtu = ifr->ifr_metric; 457 return (0); 458} 459 460void 461printall() 462{ 463 char inbuf[8192]; 464 const struct sockaddr_dl *sdl = NULL; 465 struct ifconf ifc; 466 struct ifreq ifreq, *ifr; 467 int i, idx; 468 469 ifc.ifc_len = sizeof(inbuf); 470 ifc.ifc_buf = inbuf; 471 getsock(af); 472 if (s < 0) 473 err(1, "socket"); 474 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) 475 err(1, "SIOCGIFCONF"); 476 ifr = ifc.ifc_req; 477 ifreq.ifr_name[0] = '\0'; 478 for (i = 0, idx = 0; i < ifc.ifc_len; ) { 479 ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i); 480 i += sizeof(ifr->ifr_name) + 481 (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) 482 ? ifr->ifr_addr.sa_len 483 : sizeof(struct sockaddr)); 484 if (ifr->ifr_addr.sa_family == AF_LINK) 485 sdl = (const struct sockaddr_dl *) &ifr->ifr_addr; 486 if (!strncmp(ifreq.ifr_name, ifr->ifr_name, 487 sizeof(ifr->ifr_name))) 488 continue; 489 (void) strncpy(name, ifr->ifr_name, sizeof(ifr->ifr_name)); 490 ifreq = *ifr; 491 492 if (getinfo(&ifreq) < 0) 493 continue; 494 if (dflag && (flags & IFF_UP) != 0) 495 continue; 496 if (uflag && (flags & IFF_UP) == 0) 497 continue; 498 499 idx++; 500 /* 501 * Are we just listing the interfaces? 502 */ 503 if (lflag) { 504 if (idx > 1) 505 putchar(' '); 506 fputs(name, stdout); 507 continue; 508 } 509 510 if (sdl == NULL) { 511 status(NULL, 0); 512 } else { 513 status(LLADDR(sdl), sdl->sdl_alen); 514 sdl = NULL; 515 } 516 } 517 if (lflag) 518 putchar('\n'); 519} 520 521#define RIDADDR 0 522#define ADDR 1 523#define MASK 2 524#define DSTADDR 3 525 526/*ARGSUSED*/ 527void 528setifaddr(addr, param) 529 char *addr; 530 int param; 531{ 532 /* 533 * Delay the ioctl to set the interface addr until flags are all set. 534 * The address interpretation may depend on the flags, 535 * and the flags may change when the address is set. 536 */ 537 setaddr++; 538 if (newaddr == -1) 539 newaddr = 1; 540 if (doalias == 0) 541 clearaddr = 1; 542 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 543} 544 545void 546setifnetmask(addr, d) 547 char *addr; 548 int d; 549{ 550 (*afp->af_getaddr)(addr, MASK); 551} 552 553void 554setifbroadaddr(addr, d) 555 char *addr; 556 int d; 557{ 558 (*afp->af_getaddr)(addr, DSTADDR); 559} 560 561void 562setifipdst(addr, d) 563 char *addr; 564 int d; 565{ 566 in_getaddr(addr, DSTADDR); 567 setipdst++; 568 clearaddr = 0; 569 newaddr = 0; 570} 571 572#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 573/*ARGSUSED*/ 574void 575notealias(addr, param) 576 char *addr; 577 int param; 578{ 579 if (setaddr && doalias == 0 && param < 0) 580 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), 581 rqtosa(af_addreq)->sa_len); 582 doalias = param; 583 if (param < 0) { 584 clearaddr = 1; 585 newaddr = 0; 586 } else 587 clearaddr = 0; 588} 589 590/*ARGSUSED*/ 591void 592notrailers(vname, value) 593 char *vname; 594 int value; 595{ 596 puts("Note: trailers are no longer sent, but always received"); 597} 598 599/*ARGSUSED*/ 600void 601setifdstaddr(addr, param) 602 char *addr; 603 int param; 604{ 605 (*afp->af_getaddr)(addr, DSTADDR); 606} 607 608void 609setifflags(vname, value) 610 char *vname; 611 int value; 612{ 613 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) 614 err(1, "SIOCGIFFLAGS"); 615 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 616 flags = ifr.ifr_flags; 617 618 if (value < 0) { 619 value = -value; 620 flags &= ~value; 621 } else 622 flags |= value; 623 ifr.ifr_flags = flags; 624 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) 625 err(1, "SIOCSIFFLAGS"); 626} 627 628void 629setifmetric(val, d) 630 char *val; 631 int d; 632{ 633 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 634 ifr.ifr_metric = atoi(val); 635 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 636 warn("SIOCSIFMETRIC"); 637} 638 639void 640setifmtu(val, d) 641 char *val; 642 int d; 643{ 644 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 645 ifr.ifr_metric = atoi(val); 646 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 647 warn("SIOCSIFMTU"); 648} 649 650void 651setmedia(val, d) 652 char *val; 653 int d; 654{ 655 struct ifmediareq ifmr; 656 int first_type, subtype; 657 658 (void) memset(&ifmr, 0, sizeof(ifmr)); 659 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 660 661 ifmr.ifm_count = 1; 662 ifmr.ifm_ulist = &first_type; 663 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 664 /* 665 * If we get E2BIG, the kernel is telling us 666 * that there are more, so we can ignore it. 667 */ 668 if (errno != E2BIG) 669 err(1, "SIOCGIFMEDIA"); 670 } 671 672 if (ifmr.ifm_count == 0) 673 errx(1, "%s: no media types?", name); 674 675 /* 676 * We are primarily concerned with the top-level type. 677 * However, "current" may be only IFM_NONE, so we just look 678 * for the top-level type in the first "supported type" 679 * entry. 680 * 681 * (I'm assuming that all supported media types for a given 682 * interface will be the same top-level type..) 683 */ 684 subtype = get_media_subtype(IFM_TYPE(first_type), val); 685 686 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 687 ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) | 688 IFM_TYPE(first_type) | subtype; 689 690 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 691 err(1, "SIOCSIFMEDIA"); 692} 693 694void 695setmediaopt(val, d) 696 char *val; 697 int d; 698{ 699 700 domediaopt(val, 0); 701} 702 703void 704unsetmediaopt(val, d) 705 int d; 706 char *val; 707{ 708 709 domediaopt(val, 1); 710} 711 712void 713domediaopt(val, clear) 714 char *val; 715 int clear; 716{ 717 struct ifmediareq ifmr; 718 int *mwords, options; 719 720 (void) memset(&ifmr, 0, sizeof(ifmr)); 721 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 722 723 /* 724 * We must go through the motions of reading all 725 * supported media because we need to know both 726 * the current media type and the top-level type. 727 */ 728 729 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 730 err(1, "SIOCGIFMEDIA"); 731 732 if (ifmr.ifm_count == 0) 733 errx(1, "%s: no media types?", name); 734 735 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int)); 736 if (mwords == NULL) 737 err(1, "malloc"); 738 739 ifmr.ifm_ulist = mwords; 740 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 741 err(1, "SIOCGIFMEDIA"); 742 743 options = get_media_options(IFM_TYPE(mwords[0]), val); 744 745 free(mwords); 746 747 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 748 ifr.ifr_media = ifmr.ifm_current; 749 if (clear) 750 ifr.ifr_media &= ~options; 751 else 752 ifr.ifr_media |= options; 753 754 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 755 err(1, "SIOCSIFMEDIA"); 756} 757 758/********************************************************************** 759 * A good chunk of this is duplicated from sys/net/ifmedia.c 760 **********************************************************************/ 761 762struct ifmedia_description ifm_type_descriptions[] = 763 IFM_TYPE_DESCRIPTIONS; 764 765struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 766 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 767 768struct ifmedia_description ifm_subtype_ethernet_aliases[] = 769 IFM_SUBTYPE_ETHERNET_ALIASES; 770 771struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 772 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 773 774struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 775 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 776 777struct ifmedia_description ifm_subtype_tokenring_aliases[] = 778 IFM_SUBTYPE_TOKENRING_ALIASES; 779 780struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 781 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 782 783struct ifmedia_description ifm_subtype_fddi_descriptions[] = 784 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 785 786struct ifmedia_description ifm_subtype_fddi_aliases[] = 787 IFM_SUBTYPE_FDDI_ALIASES; 788 789struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 790 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 791 792struct ifmedia_description ifm_subtype_shared_descriptions[] = 793 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 794 795struct ifmedia_description ifm_subtype_shared_aliases[] = 796 IFM_SUBTYPE_SHARED_ALIASES; 797 798struct ifmedia_description ifm_shared_option_descriptions[] = 799 IFM_SHARED_OPTION_DESCRIPTIONS; 800 801struct ifmedia_type_to_subtype { 802 struct { 803 struct ifmedia_description *desc; 804 int alias; 805 } subtypes[5]; 806 struct { 807 struct ifmedia_description *desc; 808 int alias; 809 } options[3]; 810}; 811 812/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 813struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { 814 { 815 { 816 { &ifm_subtype_shared_descriptions[0], 0 }, 817 { &ifm_subtype_shared_aliases[0], 1 }, 818 { &ifm_subtype_ethernet_descriptions[0], 0 }, 819 { &ifm_subtype_ethernet_aliases[0], 1 }, 820 { NULL, 0 }, 821 }, 822 { 823 { &ifm_shared_option_descriptions[0], 0 }, 824 { &ifm_subtype_ethernet_option_descriptions[0], 1 }, 825 { NULL, 0 }, 826 }, 827 }, 828 { 829 { 830 { &ifm_subtype_shared_descriptions[0], 0 }, 831 { &ifm_subtype_shared_aliases[0], 1 }, 832 { &ifm_subtype_tokenring_descriptions[0], 0 }, 833 { &ifm_subtype_tokenring_aliases[0], 1 }, 834 { NULL, 0 }, 835 }, 836 { 837 { &ifm_shared_option_descriptions[0], 0 }, 838 { &ifm_subtype_tokenring_option_descriptions[0], 1 }, 839 { NULL, 0 }, 840 }, 841 }, 842 { 843 { 844 { &ifm_subtype_shared_descriptions[0], 0 }, 845 { &ifm_subtype_shared_aliases[0], 1 }, 846 { &ifm_subtype_fddi_descriptions[0], 0 }, 847 { &ifm_subtype_fddi_aliases[0], 1 }, 848 { NULL, 0 }, 849 }, 850 { 851 { &ifm_shared_option_descriptions[0], 0 }, 852 { &ifm_subtype_fddi_option_descriptions[0], 1 }, 853 { NULL, 0 }, 854 }, 855 }, 856}; 857 858int 859get_media_subtype(type, val) 860 int type; 861 char *val; 862{ 863 struct ifmedia_description *desc; 864 struct ifmedia_type_to_subtype *ttos; 865 int rval, i; 866 867 /* Find the top-level interface type. */ 868 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 869 desc->ifmt_string != NULL; desc++, ttos++) 870 if (type == desc->ifmt_word) 871 break; 872 if (desc->ifmt_string == NULL) 873 errx(1, "unknown media type 0x%x", type); 874 875 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 876 rval = lookup_media_word(ttos->subtypes[i].desc, val); 877 if (rval != -1) 878 return (rval); 879 } 880 errx(1, "unknown media subtype: %s", val); 881 /* NOTREACHED */ 882} 883 884int 885get_media_options(type, val) 886 int type; 887 char *val; 888{ 889 struct ifmedia_description *desc; 890 struct ifmedia_type_to_subtype *ttos; 891 char *optlist; 892 int option = 0, i, rval = 0; 893 894 /* We muck with the string, so copy it. */ 895 optlist = strdup(val); 896 if (optlist == NULL) 897 err(1, "strdup"); 898 val = optlist; 899 900 /* Find the top-level interface type. */ 901 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 902 desc->ifmt_string != NULL; desc++, ttos++) 903 if (type == desc->ifmt_word) 904 break; 905 if (desc->ifmt_string == NULL) 906 errx(1, "unknown media type 0x%x", type); 907 908 /* 909 * Look up the options in the user-provided comma-separated 910 * list. 911 */ 912 for (; (val = strtok(val, ",")) != NULL; val = NULL) { 913 for (i = 0; ttos->options[i].desc != NULL; i++) { 914 option = lookup_media_word(ttos->options[i].desc, val); 915 if (option != -1) 916 break; 917 } 918 if (option == 0) 919 errx(1, "unknown option: %s", val); 920 rval |= option; 921 } 922 923 free(optlist); 924 return (rval); 925} 926 927int 928lookup_media_word(desc, val) 929 struct ifmedia_description *desc; 930 char *val; 931{ 932 933 for (; desc->ifmt_string != NULL; desc++) 934 if (strcasecmp(desc->ifmt_string, val) == 0) 935 return (desc->ifmt_word); 936 937 return (-1); 938} 939 940void 941print_media_word(ifmw) 942 int ifmw; 943{ 944 struct ifmedia_description *desc; 945 struct ifmedia_type_to_subtype *ttos; 946 int seen_option = 0, i; 947 948 /* Find the top-level interface type. */ 949 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 950 desc->ifmt_string != NULL; desc++, ttos++) 951 if (IFM_TYPE(ifmw) == desc->ifmt_word) 952 break; 953 if (desc->ifmt_string == NULL) { 954 printf("<unknown type>"); 955 return; 956 } 957 958 /* 959 * Don't print the top-level type; it's not like we can 960 * change it, or anything. 961 */ 962 963 /* Find subtype. */ 964 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 965 if (ttos->subtypes[i].alias) 966 continue; 967 for (desc = ttos->subtypes[i].desc; 968 desc->ifmt_string != NULL; desc++) { 969 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) 970 goto got_subtype; 971 } 972 } 973 974 /* Falling to here means unknown subtype. */ 975 printf("<unknown subtype>"); 976 return; 977 978 got_subtype: 979 printf("%s", desc->ifmt_string); 980 981 /* Find options. */ 982 for (i = 0; ttos->options[i].desc != NULL; i++) { 983 if (ttos->options[i].alias) 984 continue; 985 for (desc = ttos->options[i].desc; 986 desc->ifmt_string != NULL; desc++) { 987 if (ifmw & desc->ifmt_word) { 988 if (seen_option == 0) 989 printf(" <"); 990 printf("%s%s", seen_option++ ? "," : "", 991 desc->ifmt_string); 992 } 993 } 994 } 995 printf("%s", seen_option ? ">" : ""); 996} 997 998/********************************************************************** 999 * ...until here. 1000 **********************************************************************/ 1001 1002#define IFFBITS \ 1003"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 1004\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 1005 1006/* 1007 * Print the status of the interface. If an address family was 1008 * specified, show it and it only; otherwise, show them all. 1009 */ 1010void 1011status(ap, alen) 1012 const u_int8_t *ap; 1013 int alen; 1014{ 1015 register struct afswtch *p = afp; 1016 struct ifmediareq ifmr; 1017 int *media_list, i; 1018 1019 printf("%s: ", name); 1020 printb("flags", flags, IFFBITS); 1021 if (metric) 1022 printf(" metric %d", metric); 1023 if (mtu) 1024 printf(" mtu %d", mtu); 1025 putchar('\n'); 1026 if (ap && alen > 0) { 1027 printf("\taddress:"); 1028 for (i = 0; i < alen; i++, ap++) 1029 printf("%c%02x", i > 0 ? ':' : ' ', *ap); 1030 putchar('\n'); 1031 } 1032 1033 (void) memset(&ifmr, 0, sizeof(ifmr)); 1034 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1035 1036 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1037 /* 1038 * Interface doesn't support SIOC{G,S}IFMEDIA. 1039 */ 1040 goto proto_status; 1041 } 1042 1043 if (ifmr.ifm_count == 0) { 1044 warnx("%s: no media types?", name); 1045 goto proto_status; 1046 } 1047 1048 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 1049 if (media_list == NULL) 1050 err(1, "malloc"); 1051 ifmr.ifm_ulist = media_list; 1052 1053 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 1054 err(1, "SIOCGIFMEDIA"); 1055 1056 printf("\tmedia: "); 1057 print_media_word(ifmr.ifm_current); 1058 if (ifmr.ifm_active != ifmr.ifm_current) { 1059 putchar(' '); 1060 putchar('('); 1061 print_media_word(ifmr.ifm_active); 1062 putchar(')'); 1063 } 1064 1065 if (ifmr.ifm_status & IFM_AVALID) { 1066 printf(" status: "); 1067 switch (IFM_TYPE(ifmr.ifm_active)) { 1068 case IFM_ETHER: 1069 if (ifmr.ifm_status & IFM_ACTIVE) 1070 printf("active"); 1071 else 1072 printf("no carrier"); 1073 break; 1074 1075 case IFM_FDDI: 1076 case IFM_TOKEN: 1077 if (ifmr.ifm_status & IFM_ACTIVE) 1078 printf("inserted"); 1079 else 1080 printf("no ring"); 1081 break; 1082 } 1083 } 1084 1085 putchar('\n'); 1086 1087 if (mflag) { 1088 printf("\tsupported media:"); 1089 for (i = 0; i < ifmr.ifm_count; i++) { 1090 putchar(' '); 1091 print_media_word(media_list[i]); 1092 } 1093 putchar('\n'); 1094 } 1095 1096 free(media_list); 1097 1098 proto_status: 1099 if ((p = afp) != NULL) { 1100 (*p->af_status)(1); 1101 } else for (p = afs; p->af_name; p++) { 1102 ifr.ifr_addr.sa_family = p->af_af; 1103 (*p->af_status)(0); 1104 } 1105} 1106 1107void 1108in_status(force) 1109 int force; 1110{ 1111 struct sockaddr_in *sin; 1112 1113 getsock(AF_INET); 1114 if (s < 0) { 1115 if (errno == EPROTONOSUPPORT) 1116 return; 1117 err(1, "socket"); 1118 } 1119 (void) memset(&ifr, 0, sizeof(ifr)); 1120 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1121 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1122 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1123 if (!force) 1124 return; 1125 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1126 } else 1127 warn("SIOCGIFADDR"); 1128 } 1129 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1130 sin = (struct sockaddr_in *)&ifr.ifr_addr; 1131 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 1132 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1133 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 1134 if (errno != EADDRNOTAVAIL) 1135 warn("SIOCGIFNETMASK"); 1136 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1137 } else 1138 netmask.sin_addr = 1139 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 1140 if (flags & IFF_POINTOPOINT) { 1141 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1142 if (errno == EADDRNOTAVAIL) 1143 (void) memset(&ifr.ifr_addr, 0, 1144 sizeof(ifr.ifr_addr)); 1145 else 1146 warn("SIOCGIFDSTADDR"); 1147 } 1148 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1149 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 1150 printf("--> %s ", inet_ntoa(sin->sin_addr)); 1151 } 1152 printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr)); 1153 if (flags & IFF_BROADCAST) { 1154 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 1155 if (errno == EADDRNOTAVAIL) 1156 (void) memset(&ifr.ifr_addr, 0, 1157 sizeof(ifr.ifr_addr)); 1158 else 1159 warn("SIOCGIFBRDADDR"); 1160 } 1161 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1162 sin = (struct sockaddr_in *)&ifr.ifr_addr; 1163 if (sin->sin_addr.s_addr != 0) 1164 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 1165 } 1166 putchar('\n'); 1167} 1168 1169#ifndef INET_ONLY 1170 1171void 1172at_status(force) 1173 int force; 1174{ 1175 struct sockaddr_at *sat, null_sat; 1176 struct netrange *nr; 1177 1178 getsock(AF_APPLETALK); 1179 if (s < 0) { 1180 if (errno == EPROTONOSUPPORT) 1181 return; 1182 err(1, "socket"); 1183 } 1184 (void) memset(&ifr, 0, sizeof(ifr)); 1185 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1186 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1187 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1188 if (!force) 1189 return; 1190 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1191 } else 1192 warn("SIOCGIFADDR"); 1193 } 1194 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 1195 sat = (struct sockaddr_at *)&ifr.ifr_addr; 1196 1197 (void) memset(&null_sat, 0, sizeof(null_sat)); 1198 1199 nr = (struct netrange *) &sat->sat_zero; 1200 printf("\tatalk %d.%d range %d-%d phase %d", 1201 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1202 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 1203 if (flags & IFF_POINTOPOINT) { 1204 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1205 if (errno == EADDRNOTAVAIL) 1206 (void) memset(&ifr.ifr_addr, 0, 1207 sizeof(ifr.ifr_addr)); 1208 else 1209 warn("SIOCGIFDSTADDR"); 1210 } 1211 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1212 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr; 1213 if (!sat) 1214 sat = &null_sat; 1215 printf("--> %d.%d", 1216 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 1217 } 1218 if (flags & IFF_BROADCAST) { 1219 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1220 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr; 1221 if (sat) 1222 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net), 1223 sat->sat_addr.s_node); 1224 } 1225 putchar('\n'); 1226} 1227 1228void 1229xns_status(force) 1230 int force; 1231{ 1232 struct sockaddr_ns *sns; 1233 1234 getsock(AF_NS); 1235 if (s < 0) { 1236 if (errno == EPROTONOSUPPORT) 1237 return; 1238 err(1, "socket"); 1239 } 1240 (void) memset(&ifr, 0, sizeof(ifr)); 1241 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1242 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1243 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1244 if (!force) 1245 return; 1246 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1247 } else 1248 warn("SIOCGIFADDR"); 1249 } 1250 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 1251 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 1252 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1253 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 1254 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1255 if (errno == EADDRNOTAVAIL) 1256 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1257 else 1258 warn("SIOCGIFDSTADDR"); 1259 } 1260 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1261 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 1262 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1263 } 1264 putchar('\n'); 1265} 1266 1267void 1268iso_status(force) 1269 int force; 1270{ 1271 struct sockaddr_iso *siso; 1272 1273 getsock(AF_ISO); 1274 if (s < 0) { 1275 if (errno == EPROTONOSUPPORT) 1276 return; 1277 err(1, "socket"); 1278 } 1279 (void) memset(&ifr, 0, sizeof(ifr)); 1280 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1281 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1282 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1283 if (!force) 1284 return; 1285 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1286 } else 1287 warn("SIOCGIFADDR"); 1288 } 1289 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 1290 siso = (struct sockaddr_iso *)&ifr.ifr_addr; 1291 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 1292 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 1293 if (errno == EADDRNOTAVAIL) 1294 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1295 else 1296 warn("SIOCGIFNETMASK"); 1297 } else { 1298 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 1299 } 1300 if (flags & IFF_POINTOPOINT) { 1301 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1302 if (errno == EADDRNOTAVAIL) 1303 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1304 else 1305 warn("SIOCGIFDSTADDR"); 1306 } 1307 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1308 siso = (struct sockaddr_iso *)&ifr.ifr_addr; 1309 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 1310 } 1311 putchar('\n'); 1312} 1313 1314#endif /* INET_ONLY */ 1315 1316#define SIN(x) ((struct sockaddr_in *) &(x)) 1317struct sockaddr_in *sintab[] = { 1318SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1319SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1320 1321void 1322in_getaddr(s, which) 1323 char *s; 1324 int which; 1325{ 1326 register struct sockaddr_in *sin = sintab[which]; 1327 struct hostent *hp; 1328 struct netent *np; 1329 1330 sin->sin_len = sizeof(*sin); 1331 if (which != MASK) 1332 sin->sin_family = AF_INET; 1333 1334 if (inet_aton(s, &sin->sin_addr) == 0) { 1335 if ((hp = gethostbyname(s)) != NULL) 1336 (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); 1337 else if ((np = getnetbyname(s)) != NULL) 1338 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1339 else 1340 errx(1, "%s: bad value", s); 1341 } 1342} 1343 1344/* 1345 * Print a value a la the %b format of the kernel's printf 1346 */ 1347void 1348printb(s, v, bits) 1349 char *s; 1350 register char *bits; 1351 register unsigned short v; 1352{ 1353 register int i, any = 0; 1354 register char c; 1355 1356 if (bits && *bits == 8) 1357 printf("%s=%o", s, v); 1358 else 1359 printf("%s=%x", s, v); 1360 bits++; 1361 if (bits) { 1362 putchar('<'); 1363 while ((i = *bits++) != 0) { 1364 if (v & (1 << (i-1))) { 1365 if (any) 1366 putchar(','); 1367 any = 1; 1368 for (; (c = *bits) > 32; bits++) 1369 putchar(c); 1370 } else 1371 for (; *bits > 32; bits++) 1372 ; 1373 } 1374 putchar('>'); 1375 } 1376} 1377 1378#ifndef INET_ONLY 1379 1380void 1381at_getaddr(addr, which) 1382 char *addr; 1383 int which; 1384{ 1385 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 1386 u_int net, node; 1387 1388 sat->sat_family = AF_APPLETALK; 1389 sat->sat_len = sizeof(*sat); 1390 if (which == MASK) 1391 errx(1, "AppleTalk does not use netmasks\n"); 1392 if (sscanf(addr, "%u.%u", &net, &node) != 2 1393 || net == 0 || net > 0xffff || node == 0 || node > 0xfe) 1394 errx(1, "%s: illegal address", addr); 1395 sat->sat_addr.s_net = htons(net); 1396 sat->sat_addr.s_node = node; 1397} 1398 1399void 1400setatrange(range, d) 1401 char *range; 1402 int d; 1403{ 1404 u_short first = 123, last = 123; 1405 1406 if (sscanf(range, "%hu-%hu", &first, &last) != 2 1407 || first == 0 || first > 0xffff 1408 || last == 0 || last > 0xffff || first > last) 1409 errx(1, "%s: illegal net range: %u-%u", range, first, last); 1410 at_nr.nr_firstnet = htons(first); 1411 at_nr.nr_lastnet = htons(last); 1412} 1413 1414void 1415setatphase(phase, d) 1416 char *phase; 1417 int d; 1418{ 1419 if (!strcmp(phase, "1")) 1420 at_nr.nr_phase = 1; 1421 else if (!strcmp(phase, "2")) 1422 at_nr.nr_phase = 2; 1423 else 1424 errx(1, "%s: illegal phase", phase); 1425} 1426 1427void 1428checkatrange(sat) 1429 struct sockaddr_at *sat; 1430{ 1431 if (at_nr.nr_phase == 0) 1432 at_nr.nr_phase = 2; /* Default phase 2 */ 1433 if (at_nr.nr_firstnet == 0) 1434 at_nr.nr_firstnet = /* Default range of one */ 1435 at_nr.nr_lastnet = sat->sat_addr.s_net; 1436 printf("\tatalk %d.%d range %d-%d phase %d\n", 1437 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1438 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 1439 if ((u_short) ntohs(at_nr.nr_firstnet) > 1440 (u_short) ntohs(sat->sat_addr.s_net) 1441 || (u_short) ntohs(at_nr.nr_lastnet) < 1442 (u_short) ntohs(sat->sat_addr.s_net)) 1443 errx(1, "AppleTalk address is not in range"); 1444 *((struct netrange *) &sat->sat_zero) = at_nr; 1445} 1446 1447#define SNS(x) ((struct sockaddr_ns *) &(x)) 1448struct sockaddr_ns *snstab[] = { 1449SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 1450SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 1451 1452void 1453xns_getaddr(addr, which) 1454 char *addr; 1455 int which; 1456{ 1457 struct sockaddr_ns *sns = snstab[which]; 1458 1459 sns->sns_family = AF_NS; 1460 sns->sns_len = sizeof(*sns); 1461 sns->sns_addr = ns_addr(addr); 1462 if (which == MASK) 1463 puts("Attempt to set XNS netmask will be ineffectual"); 1464} 1465 1466#define SISO(x) ((struct sockaddr_iso *) &(x)) 1467struct sockaddr_iso *sisotab[] = { 1468SISO(ridreq.ifr_addr), SISO(iso_addreq.ifra_addr), 1469SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 1470 1471void 1472iso_getaddr(addr, which) 1473 char *addr; 1474 int which; 1475{ 1476 register struct sockaddr_iso *siso = sisotab[which]; 1477 siso->siso_addr = *iso_addr(addr); 1478 1479 if (which == MASK) { 1480 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 1481 siso->siso_nlen = 0; 1482 } else { 1483 siso->siso_len = sizeof(*siso); 1484 siso->siso_family = AF_ISO; 1485 } 1486} 1487 1488void 1489setsnpaoffset(val, d) 1490 char *val; 1491 int d; 1492{ 1493 iso_addreq.ifra_snpaoffset = atoi(val); 1494} 1495 1496void 1497setnsellength(val, d) 1498 char *val; 1499 int d; 1500{ 1501 nsellength = atoi(val); 1502 if (nsellength < 0) 1503 errx(1, "Negative NSEL length is absurd"); 1504 if (afp == 0 || afp->af_af != AF_ISO) 1505 errx(1, "Setting NSEL length valid only for iso"); 1506} 1507 1508void 1509fixnsel(s) 1510 register struct sockaddr_iso *s; 1511{ 1512 if (s->siso_family == 0) 1513 return; 1514 s->siso_tlen = nsellength; 1515} 1516 1517void 1518adjust_nsellength() 1519{ 1520 fixnsel(sisotab[RIDADDR]); 1521 fixnsel(sisotab[ADDR]); 1522 fixnsel(sisotab[DSTADDR]); 1523} 1524 1525#endif /* INET_ONLY */ 1526 1527void 1528usage() 1529{ 1530 fprintf(stderr, 1531 "usage: ifconfig [ -m ] interface\n%s%s%s%s%s%s%s%s%s%s%s", 1532 "\t[ af [ address [ dest_addr ] ] [ up ] [ down ] ", 1533 "[ netmask mask ] ]\n", 1534 "\t[ metric n ]\n", 1535 "\t[ mtu n ]\n", 1536 "\t[ arp | -arp ]\n", 1537 "\t[ media mtype ]\n", 1538 "\t[ mediaopt mopts ]\n", 1539 "\t[ -mediaopt mopts ]\n", 1540 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n", 1541 " ifconfig -a [ -m ] [ -d ] [ -u ] [ af ]\n", 1542 " ifconfig -l [ -d ] [ -u ]\n"); 1543 exit(1); 1544} 1545