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