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