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