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