1 /* $OpenBSD: ifconfig.c,v 1.54 2001/11/05 07:39:16 mpech Exp $ */ 2 /* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 /*- 38 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 39 * All rights reserved. 40 * 41 * This code is derived from software contributed to The NetBSD Foundation 42 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 43 * NASA Ames Research Center. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by the NetBSD 56 * Foundation, Inc. and its contributors. 57 * 4. Neither the name of The NetBSD Foundation nor the names of its 58 * contributors may be used to endorse or promote products derived 59 * from this software without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 62 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 63 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 64 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 65 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 68 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 69 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 70 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 71 * POSSIBILITY OF SUCH DAMAGE. 72 */ 73 74 #ifndef lint 75 static const char copyright[] = 76 "@(#) Copyright (c) 1983, 1993\n\ 77 The Regents of the University of California. All rights reserved.\n"; 78 #endif /* not lint */ 79 80 #ifndef lint 81 #if 0 82 static const char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; 83 #else 84 static const char rcsid[] = "$OpenBSD: ifconfig.c,v 1.54 2001/11/05 07:39:16 mpech Exp $"; 85 #endif 86 #endif /* not lint */ 87 88 #include <sys/param.h> 89 #include <sys/socket.h> 90 #include <sys/ioctl.h> 91 92 #include <net/if.h> 93 #include <net/if_dl.h> 94 #include <net/if_media.h> 95 #include <netinet/in.h> 96 #include <netinet/in_var.h> 97 #include <netinet6/nd6.h> 98 #include <arpa/inet.h> 99 #include <netinet/ip_ipsp.h> 100 #include <netinet/if_ether.h> 101 #include <net/if_enc.h> 102 #include <net/if_ieee80211.h> 103 104 #include <netatalk/at.h> 105 106 #define NSIP 107 #include <netns/ns.h> 108 #include <netns/ns_if.h> 109 110 #define IPXIP 111 #include <netipx/ipx.h> 112 #include <netipx/ipx_if.h> 113 114 #include <netdb.h> 115 116 #define EON 117 #include <netiso/iso.h> 118 #include <netiso/iso_var.h> 119 #include <sys/protosw.h> 120 121 #ifndef INET_ONLY 122 #include <net/if_vlan_var.h> 123 #endif 124 125 #include <ctype.h> 126 #include <err.h> 127 #include <errno.h> 128 #include <stdio.h> 129 #include <stdlib.h> 130 #include <string.h> 131 #include <unistd.h> 132 #ifdef HAVE_IFADDRS_H 133 #include <ifaddrs.h> 134 #endif 135 136 struct ifreq ifr, ridreq; 137 struct ifaliasreq addreq; 138 #ifdef INET6 139 struct in6_ifreq ifr6; 140 struct in6_ifreq in6_ridreq; 141 struct in6_aliasreq in6_addreq __attribute__((aligned(4))); 142 #endif 143 struct iso_ifreq iso_ridreq; 144 struct iso_aliasreq iso_addreq; 145 struct sockaddr_in netmask; 146 struct netrange at_nr; /* AppleTalk net range */ 147 148 int ipx_type = ETHERTYPE_II; 149 char name[IFNAMSIZ]; 150 int flags, metric, mtu, setaddr, setipdst, doalias; 151 int clearaddr, s; 152 int newaddr = 0; 153 int nsellength = 1; 154 int af = AF_INET; 155 int dflag, mflag, lflag, uflag; 156 int reset_if_flags; 157 int explicit_prefix = 0; 158 #ifdef INET6 159 int Lflag = 1; 160 #endif 161 162 void notealias __P((char *, int)); 163 void notrailers __P((char *, int)); 164 void setifaddr __P((char *, int)); 165 void setifdstaddr __P((char *, int)); 166 void setifflags __P((char *, int)); 167 void setifbroadaddr __P((char *)); 168 void setifipdst __P((char *)); 169 void setifmetric __P((char *)); 170 void setifmtu __P((char *, int)); 171 void setifnwid __P((char *, int)); 172 void setifnetmask __P((char *)); 173 void setifprefixlen __P((char *, int)); 174 void setnsellength __P((char *)); 175 void setsnpaoffset __P((char *)); 176 void setipxframetype __P((char *, int)); 177 void setatrange __P((char *, int)); 178 void setatphase __P((char *, int)); 179 void settunnel __P((char *, char *)); 180 void deletetunnel __P((void)); 181 #ifdef INET6 182 void setia6flags __P((char *, int)); 183 void setia6pltime __P((char *, int)); 184 void setia6vltime __P((char *, int)); 185 void setia6lifetime __P((char *, char *)); 186 #endif 187 void checkatrange __P ((struct sockaddr_at *)); 188 void setmedia __P((char *, int)); 189 void setmediaopt __P((char *, int)); 190 void unsetmediaopt __P((char *, int)); 191 void setmediainst __P((char *, int)); 192 void setvlantag __P((char *, int)); 193 void setvlandev __P((char *, int)); 194 void unsetvlandev __P((char *, int)); 195 void vlan_status (); 196 void fixnsel __P((struct sockaddr_iso *)); 197 int main __P((int, char *[])); 198 int prefix __P((void *val, int)); 199 200 /* 201 * Media stuff. Whenever a media command is first performed, the 202 * currently select media is grabbed for this interface. If `media' 203 * is given, the current media word is modifed. `mediaopt' commands 204 * only modify the set and clear words. They then operate on the 205 * current media word later. 206 */ 207 int media_current; 208 int mediaopt_set; 209 int mediaopt_clear; 210 211 int actions; /* Actions performed */ 212 213 #define A_MEDIA 0x0001 /* media command */ 214 #define A_MEDIAOPTSET 0x0002 /* mediaopt command */ 215 #define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */ 216 #define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR) 217 #define A_MEDIAINST 0x0008 /* instance or inst command */ 218 219 #define NEXTARG 0xffffff 220 #define NEXTARG2 0xfffffe 221 222 const struct cmd { 223 char *c_name; 224 int c_parameter; /* NEXTARG means next argv */ 225 int c_action; /* defered action */ 226 void (*c_func)(); 227 } cmds[] = { 228 { "up", IFF_UP, 0, setifflags } , 229 { "down", -IFF_UP, 0, setifflags }, 230 { "trailers", -1, 0, notrailers }, 231 { "-trailers", 1, 0, notrailers }, 232 { "arp", -IFF_NOARP, 0, setifflags }, 233 { "-arp", IFF_NOARP, 0, setifflags }, 234 { "debug", IFF_DEBUG, 0, setifflags }, 235 { "-debug", -IFF_DEBUG, 0, setifflags }, 236 { "alias", IFF_UP, 0, notealias }, 237 { "-alias", -IFF_UP, 0, notealias }, 238 { "delete", -IFF_UP, 0, notealias }, 239 #ifdef notdef 240 #define EN_SWABIPS 0x1000 241 { "swabips", EN_SWABIPS, 0, setifflags }, 242 { "-swabips", -EN_SWABIPS, 0, setifflags }, 243 #endif 244 { "netmask", NEXTARG, 0, setifnetmask }, 245 { "metric", NEXTARG, 0, setifmetric }, 246 { "mtu", NEXTARG, 0, setifmtu }, 247 { "nwid", NEXTARG, 0, setifnwid }, 248 { "broadcast", NEXTARG, 0, setifbroadaddr }, 249 { "ipdst", NEXTARG, 0, setifipdst }, 250 { "prefixlen", NEXTARG, 0, setifprefixlen}, 251 #ifdef INET6 252 { "anycast", IN6_IFF_ANYCAST, 0, setia6flags }, 253 { "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags }, 254 { "tentative", IN6_IFF_TENTATIVE, 0, setia6flags }, 255 { "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags }, 256 { "pltime", NEXTARG, 0, setia6pltime }, 257 { "vltime", NEXTARG, 0, setia6vltime }, 258 #endif /*INET6*/ 259 #ifndef INET_ONLY 260 { "range", NEXTARG, 0, setatrange }, 261 { "phase", NEXTARG, 0, setatphase }, 262 { "snpaoffset", NEXTARG, 0, setsnpaoffset }, 263 { "nsellength", NEXTARG, 0, setnsellength }, 264 { "802.2", ETHERTYPE_8022, 0, setipxframetype }, 265 { "802.2tr", ETHERTYPE_8022TR, 0, setipxframetype }, 266 { "802.3", ETHERTYPE_8023, 0, setipxframetype }, 267 { "snap", ETHERTYPE_SNAP, 0, setipxframetype }, 268 { "EtherII", ETHERTYPE_II, 0, setipxframetype }, 269 { "vlan", NEXTARG, 0, setvlantag }, 270 { "vlandev", NEXTARG, 0, setvlandev }, 271 { "-vlandev", 1, 0, unsetvlandev }, 272 #endif /* INET_ONLY */ 273 /* giftunnel is for backward compat */ 274 { "giftunnel", NEXTARG2, 0, settunnel } , 275 { "tunnel", NEXTARG2, 0, settunnel } , 276 { "deletetunnel", 0, 0, deletetunnel } , 277 { "link0", IFF_LINK0, 0, setifflags } , 278 { "-link0", -IFF_LINK0, 0, setifflags } , 279 { "link1", IFF_LINK1, 0, setifflags } , 280 { "-link1", -IFF_LINK1, 0, setifflags } , 281 { "link2", IFF_LINK2, 0, setifflags } , 282 { "-link2", -IFF_LINK2, 0, setifflags } , 283 { "media", NEXTARG, A_MEDIA, setmedia }, 284 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt }, 285 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt }, 286 { "instance", NEXTARG, A_MEDIAINST, setmediainst }, 287 { "inst", NEXTARG, A_MEDIAINST, setmediainst }, 288 { NULL, /*src*/ 0, 0, setifaddr }, 289 { NULL, /*dst*/ 0, 0, setifdstaddr }, 290 { NULL, /*illegal*/0, 0, NULL }, 291 }; 292 293 void adjust_nsellength(); 294 int getinfo __P((struct ifreq *)); 295 void getsock __P((int)); 296 void printif __P((struct ifreq *, int)); 297 void printb __P((char *, unsigned short, char *)); 298 void status __P((int)); 299 void usage(); 300 char *sec2str __P((time_t)); 301 302 const char *get_media_type_string __P((int)); 303 const char *get_media_subtype_string __P((int)); 304 int get_media_subtype __P((int, const char *)); 305 int get_media_options __P((int, const char *)); 306 int lookup_media_word __P((const struct ifmedia_description *, int, 307 const char *)); 308 void print_media_word __P((int, int, int)); 309 void process_media_commands __P((void)); 310 void init_current_media __P((void)); 311 312 /* 313 * XNS support liberally adapted from code written at the University of 314 * Maryland principally by James O'Toole and Chris Torek. 315 */ 316 void in_status __P((int)); 317 void in_getaddr __P((char *, int)); 318 void in_getprefix __P((char *, int)); 319 #ifdef INET6 320 void in6_fillscopeid __P((struct sockaddr_in6 *sin6)); 321 void in6_alias __P((struct in6_ifreq *)); 322 void in6_status __P((int)); 323 void in6_getaddr __P((char *, int)); 324 void in6_getprefix __P((char *, int)); 325 #endif 326 void at_status __P((int)); 327 void at_getaddr __P((char *, int)); 328 void xns_status __P((int)); 329 void xns_getaddr __P((char *, int)); 330 void ipx_status __P((int)); 331 void ipx_getaddr __P((char *, int)); 332 void iso_status __P((int)); 333 void iso_getaddr __P((char *, int)); 334 void ieee80211_status __P((void)); 335 336 /* Known address families */ 337 const struct afswtch { 338 char *af_name; 339 short af_af; 340 void (*af_status)(); 341 void (*af_getaddr)(); 342 void (*af_getprefix)(); 343 u_long af_difaddr; 344 u_long af_aifaddr; 345 caddr_t af_ridreq; 346 caddr_t af_addreq; 347 } afs[] = { 348 #define C(x) ((caddr_t) &x) 349 { "inet", AF_INET, in_status, in_getaddr, in_getprefix, 350 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 351 #ifdef INET6 352 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 353 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, C(in6_ridreq), C(in6_addreq) }, 354 #endif 355 #ifndef INET_ONLY /* small version, for boot media */ 356 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 357 SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) }, 358 { "ns", AF_NS, xns_status, xns_getaddr, NULL, 359 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 360 { "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL, 361 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, 362 { "iso", AF_ISO, iso_status, iso_getaddr, NULL, 363 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) }, 364 #endif /* INET_ONLY */ 365 { 0, 0, 0, 0 } 366 }; 367 368 const struct afswtch *afp; /*the address family being set or asked about*/ 369 370 int 371 main(argc, argv) 372 int argc; 373 char *argv[]; 374 { 375 const struct afswtch *rafp = NULL; 376 int aflag = 0; 377 int ifaliases = 0; 378 int i; 379 380 if (argc < 2) 381 usage(); 382 argc--, argv++; 383 if (!strcmp(*argv, "-a")) 384 aflag = 1; 385 else if (!strcmp(*argv, "-A")) { 386 aflag = 1; 387 ifaliases = 1; 388 } 389 else if (!strcmp(*argv, "-ma") || !strcmp(*argv, "-am")) { 390 aflag = 1; 391 mflag = 1; 392 } 393 else if (!strcmp(*argv, "-mA") || !strcmp(*argv, "-Am")) { 394 aflag = 1; 395 ifaliases = 1; 396 mflag = 1; 397 } 398 else if (!strcmp(*argv, "-m")) { 399 mflag = 1; 400 argc--, argv++; 401 if (argc < 1) 402 usage(); 403 (void) strlcpy(name, *argv, sizeof(name)); 404 } else 405 (void) strlcpy(name, *argv, sizeof(name)); 406 argc--, argv++; 407 if (argc > 0) { 408 for (afp = rafp = afs; rafp->af_name; rafp++) 409 if (strcmp(rafp->af_name, *argv) == 0) { 410 afp = rafp; argc--; argv++; 411 break; 412 } 413 rafp = afp; 414 af = ifr.ifr_addr.sa_family = rafp->af_af; 415 } 416 if (aflag) { 417 if (argc > 0) 418 usage(); 419 printif(NULL, ifaliases); 420 exit(0); 421 } 422 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 423 if (argc == 0) { 424 printif(&ifr, 1); 425 exit(0); 426 } 427 428 #ifdef INET6 429 /* initialization */ 430 in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 431 in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 432 #endif 433 434 if (getinfo(&ifr) < 0) 435 exit(1); 436 while (argc > 0) { 437 const struct cmd *p; 438 439 for (p = cmds; p->c_name; p++) 440 if (strcmp(*argv, p->c_name) == 0) 441 break; 442 if (p->c_name == 0 && setaddr) 443 for (i = setaddr; i > 0; i--) { 444 p++; 445 if (p->c_func == NULL) 446 errx(1, "extra address not accepted"); 447 } 448 if (p->c_func) { 449 if (p->c_parameter == NEXTARG) { 450 if (argv[1] == NULL) 451 errx(1, "'%s' requires argument", 452 p->c_name); 453 (*p->c_func)(argv[1]); 454 argc--, argv++; 455 } else if (p->c_parameter == NEXTARG2) { 456 if ((argv[1] == NULL) || 457 (argv[2] == NULL)) 458 errx(1, "'%s' requires 2 arguments", 459 p->c_name); 460 (*p->c_func)(argv[1], argv[2]); 461 argc -= 2; 462 argv += 2; 463 } else 464 (*p->c_func)(*argv, p->c_parameter); 465 actions |= p->c_action; 466 } 467 argc--, argv++; 468 } 469 470 /* Process any media commands that may have been issued. */ 471 process_media_commands(); 472 473 if (af == AF_INET6 && explicit_prefix == 0) { 474 /* 475 * Aggregatable address architecture defines all prefixes 476 * are 64. So, it is convenient to set prefixlen to 64 if 477 * it is not specified. 478 */ 479 setifprefixlen("64", 0); 480 /* in6_getprefix("64", MASK) if MASK is available here... */ 481 } 482 483 #ifndef INET_ONLY 484 485 switch (af) { 486 case AF_ISO: 487 adjust_nsellength(); 488 break; 489 case AF_NS: 490 if (setipdst) { 491 struct nsip_req rq; 492 int size = sizeof(rq); 493 494 rq.rq_ns = addreq.ifra_addr; 495 rq.rq_ip = addreq.ifra_dstaddr; 496 497 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 498 warn("encapsulation routing"); 499 } 500 break; 501 case AF_IPX: 502 if (setipdst) { 503 struct ipxip_req rq; 504 int size = sizeof(rq); 505 506 rq.rq_ipx = addreq.ifra_addr; 507 rq.rq_ip = addreq.ifra_dstaddr; 508 509 if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0) 510 warn("encapsulation routing"); 511 } 512 break; 513 case AF_APPLETALK: 514 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 515 break; 516 } 517 #endif /* INET_ONLY */ 518 519 if (clearaddr) { 520 int ret; 521 (void) strlcpy(rafp->af_ridreq, name, sizeof(ifr.ifr_name)); 522 if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) { 523 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 524 /* means no previous address for interface */ 525 } else 526 warn("SIOCDIFADDR"); 527 } 528 } 529 if (newaddr) { 530 (void) strlcpy(rafp->af_addreq, name, sizeof(ifr.ifr_name)); 531 if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0) 532 warn("SIOCAIFADDR"); 533 } 534 exit(0); 535 } 536 537 void 538 getsock(naf) 539 int naf; 540 { 541 static int oaf = -1; 542 543 if (oaf == naf) 544 return; 545 if (oaf != -1) 546 close(s); 547 s = socket(naf, SOCK_DGRAM, 0); 548 if (s < 0) 549 oaf = -1; 550 else 551 oaf = naf; 552 } 553 554 int 555 getinfo(ifr) 556 struct ifreq *ifr; 557 { 558 559 getsock(af); 560 if (s < 0) 561 err(1, "socket"); 562 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) { 563 warn("SIOCGIFFLAGS"); 564 return (-1); 565 } 566 flags = ifr->ifr_flags; 567 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) { 568 warn("SIOCGIFMETRIC"); 569 metric = 0; 570 } else 571 metric = ifr->ifr_metric; 572 if (ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) 573 mtu = 0; 574 else 575 mtu = ifr->ifr_mtu; 576 return (0); 577 } 578 579 void 580 printif(ifrm, ifaliases) 581 struct ifreq *ifrm; 582 { 583 #ifdef HAVE_IFADDRS_H 584 struct ifaddrs *ifap, *ifa; 585 const char *namep; 586 struct ifreq *ifrp; 587 int count = 0, noinet = 1; 588 589 if (getifaddrs(&ifap) != 0) 590 err(1, "getifaddrs"); 591 592 namep = NULL; 593 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 594 if (ifrm && strncmp(ifrm->ifr_name, ifa->ifa_name, 595 sizeof(ifrm->ifr_name))) 596 continue; 597 (void) strlcpy(name, ifa->ifa_name, sizeof(name)); 598 name[sizeof(name) - 1] = '\0'; 599 600 #ifdef INET6 601 /* quickhack: sizeof(ifr) < sizeof(ifr6) */ 602 if (ifa->ifa_addr->sa_family == AF_INET6) { 603 ifrp = (struct ifreq *)&ifr6; 604 memset(&ifr6, 0, sizeof(ifr6)); 605 } else { 606 ifrp = 𝔦 607 memset(&ifr, 0, sizeof(ifr)); 608 } 609 #else 610 ifrp = 𝔦 611 memset(&ifr, 0, sizeof(ifr)); 612 #endif 613 614 strlcpy(ifrp->ifr_name, ifa->ifa_name, sizeof(ifrp->ifr_name)); 615 /* XXX boundary check? */ 616 memcpy(&ifrp->ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 617 618 if (ifa->ifa_addr->sa_family == AF_LINK) { 619 namep = ifa->ifa_name; 620 if (getinfo(ifrp) < 0) 621 continue; 622 status(1); 623 count++; 624 noinet = 1; 625 continue; 626 } 627 628 if (!namep || !strcmp(namep, ifa->ifa_name)) { 629 const struct afswtch *p; 630 631 if (ifa->ifa_addr->sa_family == AF_INET && 632 ifaliases == 0 && noinet == 0) 633 continue; 634 if ((p = afp) != NULL) { 635 if (ifa->ifa_addr->sa_family == p->af_af) 636 (*p->af_status)(1); 637 } else { 638 for (p = afs; p->af_name; p++) { 639 if (ifa->ifa_addr->sa_family == p->af_af) 640 (*p->af_status)(0); 641 } 642 } 643 count++; 644 if (ifa->ifa_addr->sa_family == AF_INET) 645 noinet = 0; 646 continue; 647 } 648 } 649 freeifaddrs(ifap); 650 if (count == 0) { 651 fprintf(stderr, "%s: no such interface\n", name); 652 exit(1); 653 } 654 #else 655 char *inbuf = NULL; 656 struct ifconf ifc; 657 struct ifreq ifreq, *ifrp; 658 int i, siz, len = 8192; 659 int count = 0, noinet = 1; 660 char ifrbuf[8192]; 661 662 getsock(af); 663 if (s < 0) 664 err(1, "socket"); 665 while (1) { 666 ifc.ifc_len = len; 667 ifc.ifc_buf = inbuf = realloc(inbuf, len); 668 if (inbuf == NULL) 669 err(1, "malloc"); 670 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) 671 err(1, "SIOCGIFCONF"); 672 if (ifc.ifc_len + sizeof(ifreq) < len) 673 break; 674 len *= 2; 675 } 676 ifrp = ifc.ifc_req; 677 ifreq.ifr_name[0] = '\0'; 678 for (i = 0; i < ifc.ifc_len; ) { 679 ifrp = (struct ifreq *)((caddr_t)ifc.ifc_req + i); 680 memcpy(ifrbuf, ifrp, sizeof(*ifrp)); 681 siz = ((struct ifreq *)ifrbuf)->ifr_addr.sa_len; 682 if (siz < sizeof(ifrp->ifr_addr)) 683 siz = sizeof(ifrp->ifr_addr); 684 siz += sizeof(ifrp->ifr_name); 685 i += siz; 686 /* avoid alignment issue */ 687 if (sizeof(ifrbuf) < siz) 688 errx(1, "ifr too big"); 689 memcpy(ifrbuf, ifrp, siz); 690 ifrp = (struct ifreq *)ifrbuf; 691 692 if (ifrm && strncmp(ifrm->ifr_name, ifrp->ifr_name, 693 sizeof(ifrp->ifr_name))) 694 continue; 695 (void) strlcpy(name, ifrp->ifr_name, sizeof(ifrp->ifr_name)); 696 if (ifrp->ifr_addr.sa_family == AF_LINK) { 697 ifreq = ifr = *ifrp; 698 if (getinfo(&ifreq) < 0) 699 continue; 700 status(1); 701 count++; 702 noinet = 1; 703 continue; 704 } 705 if (!strncmp(ifreq.ifr_name, ifrp->ifr_name, 706 sizeof(ifrp->ifr_name))) { 707 const struct afswtch *p; 708 709 if (ifrp->ifr_addr.sa_family == AF_INET && 710 ifaliases == 0 && noinet == 0) 711 continue; 712 ifr = *ifrp; 713 #ifdef INET6 714 /* quickhack: sizeof(ifr) < sizeof(ifr6) */ 715 if (ifrp->ifr_addr.sa_family == AF_INET6) 716 bcopy(ifrp, &ifr6, sizeof(ifr6)); 717 #endif 718 if ((p = afp) != NULL) { 719 if (ifr.ifr_addr.sa_family == p->af_af) 720 (*p->af_status)(1); 721 } else { 722 for (p = afs; p->af_name; p++) { 723 if (ifr.ifr_addr.sa_family == p->af_af) 724 (*p->af_status)(0); 725 } 726 } 727 count++; 728 if (ifrp->ifr_addr.sa_family == AF_INET) 729 noinet = 0; 730 continue; 731 } 732 } 733 free(inbuf); 734 if (count == 0) { 735 fprintf(stderr, "%s: no such interface\n", name); 736 exit(1); 737 } 738 #endif 739 } 740 741 #define RIDADDR 0 742 #define ADDR 1 743 #define MASK 2 744 #define DSTADDR 3 745 746 /*ARGSUSED*/ 747 void 748 setifaddr(addr, param) 749 char *addr; 750 int param; 751 { 752 /* 753 * Delay the ioctl to set the interface addr until flags are all set. 754 * The address interpretation may depend on the flags, 755 * and the flags may change when the address is set. 756 */ 757 setaddr++; 758 newaddr = 1; 759 if (doalias == 0) 760 clearaddr = 1; 761 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 762 } 763 764 void 765 settunnel(src, dst) 766 char *src; 767 char *dst; 768 { 769 struct addrinfo hints, *srcres, *dstres; 770 int ecode; 771 struct if_laddrreq req; 772 773 memset(&hints, 0, sizeof(hints)); 774 hints.ai_family = afp->af_af; 775 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 776 777 if ((ecode = getaddrinfo(src, NULL, &hints, &srcres)) != 0) 778 errx(1, "error in parsing address string: %s", 779 gai_strerror(ecode)); 780 781 if ((ecode = getaddrinfo(dst, NULL, &hints, &dstres)) != 0) 782 errx(1, "error in parsing address string: %s", 783 gai_strerror(ecode)); 784 785 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 786 errx(1, 787 "source and destination address families do not match"); 788 789 if (srcres->ai_addrlen > sizeof(req.addr) || 790 dstres->ai_addrlen > sizeof(req.dstaddr)) 791 errx(1, "invalid sockaddr"); 792 793 memset(&req, 0, sizeof(req)); 794 (void) strlcpy(req.iflr_name, name, sizeof(req.iflr_name)); 795 memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); 796 memcpy(&req.dstaddr, dstres->ai_addr, dstres->ai_addrlen); 797 if (ioctl(s, SIOCSLIFPHYADDR, &req) < 0) 798 warn("SIOCSLIFPHYADDR"); 799 800 freeaddrinfo(srcres); 801 freeaddrinfo(dstres); 802 } 803 804 void 805 deletetunnel() 806 { 807 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 808 warn("SIOCDIFPHYADDR"); 809 } 810 811 812 void 813 setifnetmask(addr) 814 char *addr; 815 { 816 (*afp->af_getaddr)(addr, MASK); 817 } 818 819 void 820 setifbroadaddr(addr) 821 char *addr; 822 { 823 (*afp->af_getaddr)(addr, DSTADDR); 824 } 825 826 void 827 setifipdst(addr) 828 char *addr; 829 { 830 in_getaddr(addr, DSTADDR); 831 setipdst++; 832 clearaddr = 0; 833 newaddr = 0; 834 } 835 836 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 837 /*ARGSUSED*/ 838 void 839 notealias(addr, param) 840 char *addr; 841 int param; 842 { 843 if (setaddr && doalias == 0 && param < 0) 844 memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), 845 rqtosa(af_addreq)->sa_len); 846 doalias = param; 847 if (param < 0) { 848 clearaddr = 1; 849 newaddr = 0; 850 } else 851 clearaddr = 0; 852 } 853 854 /*ARGSUSED*/ 855 void 856 notrailers(vname, value) 857 char *vname; 858 int value; 859 { 860 printf("Note: trailers are no longer sent, but always received\n"); 861 } 862 863 /*ARGSUSED*/ 864 void 865 setifdstaddr(addr, param) 866 char *addr; 867 int param; 868 { 869 setaddr++; 870 (*afp->af_getaddr)(addr, DSTADDR); 871 } 872 873 /* 874 * Note: doing an SIOCIGIFFLAGS scribbles on the union portion 875 * of the ifreq structure, which may confuse other parts of ifconfig. 876 * Make a private copy so we can avoid that. 877 */ 878 void 879 setifflags(vname, value) 880 char *vname; 881 int value; 882 { 883 struct ifreq my_ifr; 884 885 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 886 887 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) 888 err(1, "SIOCGIFFLAGS"); 889 (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name)); 890 flags = my_ifr.ifr_flags; 891 892 if (value < 0) { 893 value = -value; 894 flags &= ~value; 895 } else 896 flags |= value; 897 my_ifr.ifr_flags = flags; 898 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0) 899 err(1, "SIOCSIFFLAGS"); 900 } 901 902 #ifdef INET6 903 void 904 setia6flags(vname, value) 905 char *vname; 906 int value; 907 { 908 if (value < 0) { 909 value = -value; 910 in6_addreq.ifra_flags &= ~value; 911 } else 912 in6_addreq.ifra_flags |= value; 913 } 914 915 void 916 setia6pltime(val, d) 917 char *val; 918 int d; 919 { 920 setia6lifetime("pltime", val); 921 } 922 923 void 924 setia6vltime(val, d) 925 char *val; 926 int d; 927 { 928 setia6lifetime("vltime", val); 929 } 930 931 void 932 setia6lifetime(cmd, val) 933 char *cmd; 934 char *val; 935 { 936 time_t newval, t; 937 char *ep; 938 939 t = time(NULL); 940 newval = (time_t)strtoul(val, &ep, 0); 941 if (val == ep) 942 errx(1, "invalid %s", cmd); 943 if (afp->af_af != AF_INET6) 944 errx(1, "%s not allowed for the AF", cmd); 945 if (strcmp(cmd, "vltime") == 0) { 946 in6_addreq.ifra_lifetime.ia6t_expire = t + newval; 947 in6_addreq.ifra_lifetime.ia6t_vltime = newval; 948 } else if (strcmp(cmd, "pltime") == 0) { 949 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; 950 in6_addreq.ifra_lifetime.ia6t_pltime = newval; 951 } 952 } 953 #endif 954 955 void 956 setifmetric(val) 957 char *val; 958 { 959 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 960 ifr.ifr_metric = atoi(val); 961 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 962 warn("SIOCSIFMETRIC"); 963 } 964 965 void 966 setifmtu(val, d) 967 char *val; 968 int d; 969 { 970 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 971 ifr.ifr_mtu = atoi(val); 972 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 973 warn("SIOCSIFMTU"); 974 } 975 976 void 977 setifnwid(val, d) 978 char *val; 979 int d; 980 { 981 struct ieee80211_nwid nwid; 982 983 memset(&nwid, 0, sizeof(nwid)); 984 (void)strlcpy(nwid.i_nwid, val, sizeof(nwid.i_nwid)); 985 nwid.i_len = sizeof(nwid.i_nwid); 986 (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 987 ifr.ifr_data = (caddr_t)&nwid; 988 if (ioctl(s, SIOCS80211NWID, (caddr_t)&ifr) < 0) 989 warn("SIOCS80211NWID"); 990 } 991 992 void 993 ieee80211_status() 994 { 995 struct ieee80211_nwid nwid; 996 char buf[IEEE80211_NWID_LEN + 1]; 997 998 memset(&ifr, 0, sizeof(ifr)); 999 ifr.ifr_data = (caddr_t)&nwid; 1000 (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1001 if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr) == 0) { 1002 (void) strlcpy(buf, nwid.i_nwid, sizeof(buf)); 1003 printf("\tnwid %s\n", nwid.i_nwid); 1004 } 1005 } 1006 1007 void 1008 init_current_media() 1009 { 1010 struct ifmediareq ifmr; 1011 1012 /* 1013 * If we have not yet done so, grab the currently-selected 1014 * media. 1015 */ 1016 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) { 1017 (void) memset(&ifmr, 0, sizeof(ifmr)); 1018 (void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1019 1020 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1021 /* 1022 * If we get E2BIG, the kernel is telling us 1023 * that there are more, so we can ignore it. 1024 */ 1025 if (errno != E2BIG) 1026 err(1, "SGIOCGIFMEDIA"); 1027 } 1028 1029 media_current = ifmr.ifm_current; 1030 } 1031 1032 /* Sanity. */ 1033 if (IFM_TYPE(media_current) == 0) 1034 errx(1, "%s: no link type?", name); 1035 } 1036 1037 void 1038 process_media_commands() 1039 { 1040 1041 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) { 1042 /* Nothing to do. */ 1043 return; 1044 } 1045 1046 /* 1047 * Media already set up, and commands sanity-checked. Set/clear 1048 * any options, and we're ready to go. 1049 */ 1050 media_current |= mediaopt_set; 1051 media_current &= ~mediaopt_clear; 1052 1053 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1054 ifr.ifr_media = media_current; 1055 1056 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 1057 err(1, "SIOCSIFMEDIA"); 1058 } 1059 1060 void 1061 setmedia(val, d) 1062 char *val; 1063 int d; 1064 { 1065 int type, subtype, inst; 1066 1067 init_current_media(); 1068 1069 /* Only one media command may be given. */ 1070 if (actions & A_MEDIA) 1071 errx(1, "only one `media' command may be issued"); 1072 1073 /* Must not come after mediaopt commands */ 1074 if (actions & A_MEDIAOPT) 1075 errx(1, "may not issue `media' after `mediaopt' commands"); 1076 1077 /* 1078 * No need to check if `instance' has been issued; setmediainst() 1079 * craps out if `media' has not been specified. 1080 */ 1081 1082 type = IFM_TYPE(media_current); 1083 inst = IFM_INST(media_current); 1084 1085 /* Look up the subtype. */ 1086 subtype = get_media_subtype(type, val); 1087 1088 /* Build the new current media word. */ 1089 media_current = IFM_MAKEWORD(type, subtype, 0, inst); 1090 1091 /* Media will be set after other processing is complete. */ 1092 } 1093 1094 void 1095 setmediaopt(val, d) 1096 char *val; 1097 int d; 1098 { 1099 1100 init_current_media(); 1101 1102 /* Can only issue `mediaopt' once. */ 1103 if (actions & A_MEDIAOPTSET) 1104 errx(1, "only one `mediaopt' command may be issued"); 1105 1106 /* Can't issue `mediaopt' if `instance' has already been issued. */ 1107 if (actions & A_MEDIAINST) 1108 errx(1, "may not issue `mediaopt' after `instance'"); 1109 1110 mediaopt_set = get_media_options(IFM_TYPE(media_current), val); 1111 1112 /* Media will be set after other processing is complete. */ 1113 } 1114 1115 void 1116 unsetmediaopt(val, d) 1117 char *val; 1118 int d; 1119 { 1120 1121 init_current_media(); 1122 1123 /* Can only issue `-mediaopt' once. */ 1124 if (actions & A_MEDIAOPTCLR) 1125 errx(1, "only one `-mediaopt' command may be issued"); 1126 1127 /* May not issue `media' and `-mediaopt'. */ 1128 if (actions & A_MEDIA) 1129 errx(1, "may not issue both `media' and `-mediaopt'"); 1130 1131 /* 1132 * No need to check for A_MEDIAINST, since the test for A_MEDIA 1133 * implicitly checks for A_MEDIAINST. 1134 */ 1135 1136 mediaopt_clear = get_media_options(IFM_TYPE(media_current), val); 1137 1138 /* Media will be set after other processing is complete. */ 1139 } 1140 1141 void 1142 setmediainst(val, d) 1143 char *val; 1144 int d; 1145 { 1146 int type, subtype, options, inst; 1147 1148 init_current_media(); 1149 1150 /* Can only issue `instance' once. */ 1151 if (actions & A_MEDIAINST) 1152 errx(1, "only one `instance' command may be issued"); 1153 1154 /* Must have already specified `media' */ 1155 if ((actions & A_MEDIA) == 0) 1156 errx(1, "must specify `media' before `instance'"); 1157 1158 type = IFM_TYPE(media_current); 1159 subtype = IFM_SUBTYPE(media_current); 1160 options = IFM_OPTIONS(media_current); 1161 1162 inst = atoi(val); 1163 if (inst < 0 || inst > IFM_INST_MAX) 1164 errx(1, "invalid media instance: %s", val); 1165 1166 media_current = IFM_MAKEWORD(type, subtype, options, inst); 1167 1168 /* Media will be set after other processing is complete. */ 1169 } 1170 1171 const struct ifmedia_description ifm_type_descriptions[] = 1172 IFM_TYPE_DESCRIPTIONS; 1173 1174 const struct ifmedia_description ifm_subtype_descriptions[] = 1175 IFM_SUBTYPE_DESCRIPTIONS; 1176 1177 const struct ifmedia_description ifm_option_descriptions[] = 1178 IFM_OPTION_DESCRIPTIONS; 1179 1180 const char * 1181 get_media_type_string(mword) 1182 int mword; 1183 { 1184 const struct ifmedia_description *desc; 1185 1186 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; 1187 desc++) { 1188 if (IFM_TYPE(mword) == desc->ifmt_word) 1189 return (desc->ifmt_string); 1190 } 1191 return ("<unknown type>"); 1192 } 1193 1194 const char * 1195 get_media_subtype_string(mword) 1196 int mword; 1197 { 1198 const struct ifmedia_description *desc; 1199 1200 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL; 1201 desc++) { 1202 if (IFM_TYPE_MATCH(desc->ifmt_word, mword) && 1203 IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword)) 1204 return (desc->ifmt_string); 1205 } 1206 return ("<unknown subtype>"); 1207 } 1208 1209 int 1210 get_media_subtype(type, val) 1211 int type; 1212 const char *val; 1213 { 1214 int rval; 1215 1216 rval = lookup_media_word(ifm_subtype_descriptions, type, val); 1217 if (rval == -1) 1218 errx(1, "unknown %s media subtype: %s", 1219 get_media_type_string(type), val); 1220 1221 return (rval); 1222 } 1223 1224 int 1225 get_media_options(type, val) 1226 int type; 1227 const char *val; 1228 { 1229 char *optlist, *str; 1230 int option, rval = 0; 1231 1232 /* We muck with the string, so copy it. */ 1233 optlist = strdup(val); 1234 if (optlist == NULL) 1235 err(1, "strdup"); 1236 str = optlist; 1237 1238 /* 1239 * Look up the options in the user-provided comma-separated list. 1240 */ 1241 for (; (str = strtok(str, ",")) != NULL; str = NULL) { 1242 option = lookup_media_word(ifm_option_descriptions, type, str); 1243 if (option == -1) 1244 errx(1, "unknown %s media option: %s", 1245 get_media_type_string(type), str); 1246 rval |= option; 1247 } 1248 1249 free(optlist); 1250 return (rval); 1251 } 1252 1253 int 1254 lookup_media_word(desc, type, val) 1255 const struct ifmedia_description *desc; 1256 int type; 1257 const char *val; 1258 { 1259 1260 for (; desc->ifmt_string != NULL; desc++) { 1261 if (IFM_TYPE_MATCH(desc->ifmt_word, type) && 1262 strcasecmp(desc->ifmt_string, val) == 0) 1263 return (desc->ifmt_word); 1264 } 1265 return (-1); 1266 } 1267 1268 void 1269 print_media_word(ifmw, print_type, as_syntax) 1270 int ifmw, print_type, as_syntax; 1271 { 1272 const struct ifmedia_description *desc; 1273 int seen_option = 0; 1274 1275 if (print_type) 1276 printf("%s ", get_media_type_string(ifmw)); 1277 printf("%s%s", as_syntax ? "media " : "", 1278 get_media_subtype_string(ifmw)); 1279 1280 /* Find options. */ 1281 for (desc = ifm_option_descriptions; desc->ifmt_string != NULL; 1282 desc++) { 1283 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) && 1284 (ifmw & desc->ifmt_word) != 0 && 1285 (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) { 1286 if (seen_option == 0) 1287 printf(" %s", as_syntax ? "mediaopt " : ""); 1288 printf("%s%s", seen_option ? "," : "", 1289 desc->ifmt_string); 1290 seen_option |= IFM_OPTIONS(desc->ifmt_word); 1291 } 1292 } 1293 if (IFM_INST(ifmw) != 0) 1294 printf(" instance %d", IFM_INST(ifmw)); 1295 } 1296 1297 #define IFFBITS \ 1298 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 1299 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 1300 1301 static void 1302 phys_status(force) 1303 int force; 1304 { 1305 char psrcaddr[NI_MAXHOST]; 1306 char pdstaddr[NI_MAXHOST]; 1307 const char *ver = ""; 1308 #ifdef NI_WITHSCOPEID 1309 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 1310 #else 1311 const int niflag = NI_NUMERICHOST; 1312 #endif 1313 struct if_laddrreq req; 1314 1315 psrcaddr[0] = pdstaddr[0] = '\0'; 1316 1317 memset(&req, 0, sizeof(req)); 1318 (void) strlcpy(req.iflr_name, name, sizeof(req.iflr_name)); 1319 if (ioctl(s, SIOCGLIFPHYADDR, (caddr_t)&req) < 0) 1320 return; 1321 #ifdef INET6 1322 if (req.addr.ss_family == AF_INET6) 1323 in6_fillscopeid((struct sockaddr_in6 *)&req.addr); 1324 #endif 1325 getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len, 1326 psrcaddr, sizeof(psrcaddr), 0, 0, niflag); 1327 #ifdef INET6 1328 if (req.addr.ss_family == AF_INET6) 1329 ver = "6"; 1330 #endif 1331 1332 #ifdef INET6 1333 if (req.dstaddr.ss_family == AF_INET6) 1334 in6_fillscopeid((struct sockaddr_in6 *)&req.dstaddr); 1335 #endif 1336 getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len, 1337 pdstaddr, sizeof(pdstaddr), 0, 0, niflag); 1338 1339 printf("\tphysical address inet%s %s --> %s\n", ver, 1340 psrcaddr, pdstaddr); 1341 } 1342 1343 const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 1344 1345 const struct ifmedia_status_description ifm_status_descriptions[] = 1346 IFM_STATUS_DESCRIPTIONS; 1347 1348 /* 1349 * Print the status of the interface. If an address family was 1350 * specified, show it and it only; otherwise, show them all. 1351 */ 1352 void 1353 status(link) 1354 int link; 1355 { 1356 const struct afswtch *p = afp; 1357 struct ifmediareq ifmr; 1358 int *media_list, i; 1359 1360 printf("%s: ", name); 1361 printb("flags", flags, IFFBITS); 1362 if (metric) 1363 printf(" metric %d", metric); 1364 if (mtu) 1365 printf(" mtu %d", mtu); 1366 putchar('\n'); 1367 1368 #ifndef INET_ONLY 1369 vlan_status(); 1370 #endif 1371 ieee80211_status(); 1372 1373 (void) memset(&ifmr, 0, sizeof(ifmr)); 1374 (void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1375 1376 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1377 /* 1378 * Interface doesn't support SIOC{G,S}IFMEDIA. 1379 */ 1380 goto proto_status; 1381 } 1382 1383 if (ifmr.ifm_count == 0) { 1384 warnx("%s: no media types?", name); 1385 goto proto_status; 1386 } 1387 1388 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 1389 if (media_list == NULL) 1390 err(1, "malloc"); 1391 ifmr.ifm_ulist = media_list; 1392 1393 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 1394 err(1, "SIOCGIFMEDIA"); 1395 1396 printf("\tmedia: "); 1397 print_media_word(ifmr.ifm_current, 1, 0); 1398 if (ifmr.ifm_active != ifmr.ifm_current) { 1399 putchar(' '); 1400 putchar('('); 1401 print_media_word(ifmr.ifm_active, 0, 0); 1402 putchar(')'); 1403 } 1404 putchar('\n'); 1405 1406 if (ifmr.ifm_status & IFM_AVALID) { 1407 const struct ifmedia_status_description *ifms; 1408 int bitno, found = 0; 1409 1410 printf("\tstatus: "); 1411 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { 1412 for (ifms = ifm_status_descriptions; 1413 ifms->ifms_valid != 0; ifms++) { 1414 if (ifms->ifms_type != 1415 IFM_TYPE(ifmr.ifm_current) || 1416 ifms->ifms_valid != 1417 ifm_status_valid_list[bitno]) 1418 continue; 1419 printf("%s%s", found ? ", " : "", 1420 IFM_STATUS_DESC(ifms, ifmr.ifm_status)); 1421 found = 1; 1422 1423 /* 1424 * For each valid indicator bit, there's 1425 * only one entry for each media type, so 1426 * terminate the inner loop now. 1427 */ 1428 break; 1429 } 1430 } 1431 1432 if (found == 0) 1433 printf("unknown"); 1434 putchar('\n'); 1435 } 1436 1437 if (mflag) { 1438 int type, printed_type = 0; 1439 1440 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) { 1441 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { 1442 if (IFM_TYPE(media_list[i]) == type) { 1443 if (printed_type == 0) { 1444 printf("\tsupported media:\n"); 1445 printed_type = 1; 1446 } 1447 printf("\t\t"); 1448 print_media_word(media_list[i], 0, 1); 1449 printf("\n"); 1450 } 1451 } 1452 } 1453 } 1454 1455 free(media_list); 1456 1457 proto_status: 1458 if (link == 0) { 1459 if ((p = afp) != NULL) { 1460 (*p->af_status)(1); 1461 } else for (p = afs; p->af_name; p++) { 1462 ifr.ifr_addr.sa_family = p->af_af; 1463 (*p->af_status)(0); 1464 } 1465 } 1466 1467 phys_status(0); 1468 } 1469 1470 1471 void 1472 in_status(force) 1473 int force; 1474 { 1475 struct sockaddr_in *sin, sin2; 1476 char *inet_ntoa(); 1477 1478 getsock(AF_INET); 1479 if (s < 0) { 1480 if (errno == EPROTONOSUPPORT) 1481 return; 1482 err(1, "socket"); 1483 } 1484 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1485 sin = (struct sockaddr_in *)&ifr.ifr_addr; 1486 1487 /* 1488 * We keep the interface address and reset it before each 1489 * ioctl() so we can get ifaliases information (as opposed 1490 * to the primary interface netmask/dstaddr/broadaddr, if 1491 * the ifr_addr field is zero). 1492 */ 1493 memcpy(&sin2, &ifr.ifr_addr, sizeof(sin2)); 1494 1495 printf("\tinet %s ", inet_ntoa(sin->sin_addr)); 1496 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1497 if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) { 1498 if (errno != EADDRNOTAVAIL) 1499 warn("SIOCGIFNETMASK"); 1500 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1501 } else 1502 netmask.sin_addr = 1503 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 1504 if (flags & IFF_POINTOPOINT) { 1505 memcpy(&ifr.ifr_addr, &sin2, sizeof(sin2)); 1506 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1507 if (errno == EADDRNOTAVAIL) 1508 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1509 else 1510 warn("SIOCGIFDSTADDR"); 1511 } 1512 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1513 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 1514 printf("--> %s ", inet_ntoa(sin->sin_addr)); 1515 } 1516 printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr)); 1517 if (flags & IFF_BROADCAST) { 1518 memcpy(&ifr.ifr_addr, &sin2, sizeof(sin2)); 1519 if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) { 1520 if (errno == EADDRNOTAVAIL) 1521 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1522 else 1523 warn("SIOCGIFBRDADDR"); 1524 } 1525 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1526 sin = (struct sockaddr_in *)&ifr.ifr_addr; 1527 if (sin->sin_addr.s_addr != 0) 1528 printf("broadcast %s", inet_ntoa(sin->sin_addr)); 1529 } 1530 putchar('\n'); 1531 } 1532 1533 void 1534 setifprefixlen(addr, d) 1535 char *addr; 1536 int d; 1537 { 1538 if (*afp->af_getprefix) 1539 (*afp->af_getprefix)(addr, MASK); 1540 explicit_prefix = 1; 1541 } 1542 1543 #ifdef INET6 1544 void 1545 in6_fillscopeid(sin6) 1546 struct sockaddr_in6 *sin6; 1547 { 1548 #if defined(__KAME__) && defined(KAME_SCOPEID) 1549 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1550 sin6->sin6_scope_id = 1551 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 1552 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 1553 } 1554 #endif 1555 } 1556 1557 /* XXX not really an alias */ 1558 void 1559 in6_alias(creq) 1560 struct in6_ifreq *creq; 1561 { 1562 struct sockaddr_in6 *sin6; 1563 struct in6_ifreq ifr6; /* shadows file static variable */ 1564 u_int32_t scopeid; 1565 char hbuf[NI_MAXHOST]; 1566 #ifdef NI_WITHSCOPEID 1567 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 1568 #else 1569 const int niflag = NI_NUMERICHOST; 1570 #endif 1571 1572 /* Get the non-alias address for this interface. */ 1573 getsock(AF_INET6); 1574 if (s < 0) { 1575 if (errno == EPROTONOSUPPORT) 1576 return; 1577 err(1, "socket"); 1578 } 1579 1580 sin6 = (struct sockaddr_in6 *)&creq->ifr_addr; 1581 1582 in6_fillscopeid(sin6); 1583 scopeid = sin6->sin6_scope_id; 1584 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 1585 hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) 1586 strcpy(hbuf, ""); 1587 printf("\tinet6 %s", hbuf); 1588 1589 if (flags & IFF_POINTOPOINT) { 1590 (void) memset(&ifr6, 0, sizeof(ifr6)); 1591 (void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1592 ifr6.ifr_addr = creq->ifr_addr; 1593 if (ioctl(s, SIOCGIFDSTADDR_IN6, (caddr_t)&ifr6) < 0) { 1594 if (errno != EADDRNOTAVAIL) 1595 warn("SIOCGIFDSTADDR_IN6"); 1596 (void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr)); 1597 ifr6.ifr_addr.sin6_family = AF_INET6; 1598 ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6); 1599 } 1600 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 1601 in6_fillscopeid(sin6); 1602 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 1603 hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) 1604 strcpy(hbuf, ""); 1605 printf(" -> %s", hbuf); 1606 } 1607 1608 (void) memset(&ifr6, 0, sizeof(ifr6)); 1609 (void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1610 ifr6.ifr_addr = creq->ifr_addr; 1611 if (ioctl(s, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) { 1612 if (errno != EADDRNOTAVAIL) 1613 warn("SIOCGIFNETMASK_IN6"); 1614 } else { 1615 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 1616 printf(" prefixlen %d", prefix(&sin6->sin6_addr, 1617 sizeof(struct in6_addr))); 1618 } 1619 1620 (void) memset(&ifr6, 0, sizeof(ifr6)); 1621 (void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1622 ifr6.ifr_addr = creq->ifr_addr; 1623 if (ioctl(s, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) < 0) { 1624 if (errno != EADDRNOTAVAIL) 1625 warn("SIOCGIFAFLAG_IN6"); 1626 } else { 1627 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST) 1628 printf(" anycast"); 1629 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) 1630 printf(" tentative"); 1631 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) 1632 printf(" duplicated"); 1633 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED) 1634 printf(" detached"); 1635 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) 1636 printf(" deprecated"); 1637 } 1638 1639 if (scopeid) 1640 printf(" scopeid 0x%x", scopeid); 1641 1642 if (Lflag) { 1643 struct in6_addrlifetime *lifetime; 1644 (void) memset(&ifr6, 0, sizeof(ifr6)); 1645 (void) strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 1646 ifr6.ifr_addr = creq->ifr_addr; 1647 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 1648 if (ioctl(s, SIOCGIFALIFETIME_IN6, (caddr_t)&ifr6) < 0) { 1649 if (errno != EADDRNOTAVAIL) 1650 warn("SIOCGIFALIFETIME_IN6"); 1651 } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { 1652 time_t t = time(NULL); 1653 printf(" pltime "); 1654 if (lifetime->ia6t_preferred) { 1655 printf("%s", lifetime->ia6t_preferred < t 1656 ? "0" 1657 : sec2str(lifetime->ia6t_preferred - t)); 1658 } else 1659 printf("infty"); 1660 1661 printf(" vltime "); 1662 if (lifetime->ia6t_expire) { 1663 printf("%s", lifetime->ia6t_expire < t 1664 ? "0" 1665 : sec2str(lifetime->ia6t_expire - t)); 1666 } else 1667 printf("infty"); 1668 } 1669 } 1670 1671 printf("\n"); 1672 } 1673 1674 void 1675 in6_status(force) 1676 int force; 1677 { 1678 in6_alias((struct in6_ifreq *)&ifr6); 1679 } 1680 #endif /*INET6*/ 1681 1682 #ifndef INET_ONLY 1683 1684 void 1685 at_status(force) 1686 int force; 1687 { 1688 struct sockaddr_at *sat, null_sat; 1689 struct netrange *nr; 1690 1691 getsock(AF_APPLETALK); 1692 if (s < 0) { 1693 if (errno == EPROTONOSUPPORT) 1694 return; 1695 err(1, "socket"); 1696 } 1697 (void) memset(&ifr, 0, sizeof(ifr)); 1698 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1699 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1700 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1701 if (!force) 1702 return; 1703 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1704 } else 1705 warn("SIOCGIFADDR"); 1706 } 1707 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1708 sat = (struct sockaddr_at *)&ifr.ifr_addr; 1709 1710 (void) memset(&null_sat, 0, sizeof(null_sat)); 1711 1712 nr = (struct netrange *) &sat->sat_zero; 1713 printf("\tAppleTalk %d.%d range %d-%d phase %d", 1714 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 1715 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 1716 if (flags & IFF_POINTOPOINT) { 1717 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1718 if (errno == EADDRNOTAVAIL) 1719 (void) memset(&ifr.ifr_addr, 0, 1720 sizeof(ifr.ifr_addr)); 1721 else 1722 warn("SIOCGIFDSTADDR"); 1723 } 1724 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1725 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr; 1726 if (!sat) 1727 sat = &null_sat; 1728 printf("--> %d.%d", 1729 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 1730 } 1731 if (flags & IFF_BROADCAST) { 1732 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 1733 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr; 1734 if (sat) 1735 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net), 1736 sat->sat_addr.s_node); 1737 } 1738 putchar('\n'); 1739 } 1740 1741 void 1742 xns_status(force) 1743 int force; 1744 { 1745 struct sockaddr_ns *sns; 1746 1747 getsock(AF_NS); 1748 if (s < 0) { 1749 if (errno == EPROTONOSUPPORT) 1750 return; 1751 err(1, "socket"); 1752 } 1753 memset(&ifr, 0, sizeof(ifr)); 1754 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1755 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1756 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1757 if (!force) 1758 return; 1759 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1760 } else 1761 warn("SIOCGIFADDR"); 1762 } 1763 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1764 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 1765 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 1766 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 1767 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1768 if (errno == EADDRNOTAVAIL) 1769 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1770 else 1771 warn("SIOCGIFDSTADDR"); 1772 } 1773 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1774 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 1775 printf("--> %s ", ns_ntoa(sns->sns_addr)); 1776 } 1777 putchar('\n'); 1778 } 1779 1780 void 1781 setipxframetype(vname, type) 1782 char *vname; 1783 int type; 1784 { 1785 ipx_type = type; 1786 } 1787 1788 void 1789 ipx_status(force) 1790 int force; 1791 { 1792 struct sockaddr_ipx *sipx; 1793 1794 getsock(AF_IPX); 1795 if (s < 0) { 1796 if (errno == EPROTONOSUPPORT) 1797 return; 1798 err(1, "socket"); 1799 } 1800 memset(&ifr, 0, sizeof(ifr)); 1801 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1802 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 1803 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1804 if (!force) 1805 return; 1806 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1807 } else 1808 warn("SIOCGIFADDR"); 1809 } 1810 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1811 sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; 1812 printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr)); 1813 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 1814 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 1815 if (errno == EADDRNOTAVAIL) 1816 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1817 else 1818 warn("SIOCGIFDSTADDR"); 1819 } 1820 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1821 sipx = (struct sockaddr_ipx *)&ifr.ifr_dstaddr; 1822 printf("--> %s ", ipx_ntoa(sipx->sipx_addr)); 1823 } 1824 { 1825 struct frame_types { 1826 int type; 1827 char *name; 1828 } *p, frames[] = { 1829 { ETHERTYPE_8022, "802.2" }, 1830 { ETHERTYPE_8022TR, "802.2tr" }, 1831 { ETHERTYPE_8023, "802.3" }, 1832 { ETHERTYPE_SNAP, "SNAP" }, 1833 { ETHERTYPE_II, "EtherII" }, 1834 { 0, NULL } 1835 }; 1836 for (p = frames; p->name && p->type != sipx->sipx_type; p++); 1837 if (p->name != NULL) 1838 printf("frame %s ", p->name); 1839 } 1840 putchar('\n'); 1841 } 1842 1843 void 1844 iso_status(force) 1845 int force; 1846 { 1847 struct sockaddr_iso *siso; 1848 struct iso_ifreq ifr; 1849 1850 getsock(AF_ISO); 1851 if (s < 0) { 1852 if (errno == EPROTONOSUPPORT) 1853 return; 1854 err(1, "socket"); 1855 } 1856 memset(&ifr, 0, sizeof(ifr)); 1857 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1858 if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) { 1859 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 1860 if (!force) 1861 return; 1862 memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr)); 1863 } else 1864 warn("SIOCGIFADDR_ISO"); 1865 } 1866 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1867 siso = &ifr.ifr_Addr; 1868 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 1869 if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) { 1870 if (errno == EADDRNOTAVAIL) 1871 memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr)); 1872 else 1873 warn("SIOCGIFNETMASK_ISO"); 1874 } else { 1875 printf(" netmask %s ", iso_ntoa(&siso->siso_addr)); 1876 } 1877 if (flags & IFF_POINTOPOINT) { 1878 if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) { 1879 if (errno == EADDRNOTAVAIL) 1880 memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr)); 1881 else 1882 warn("SIOCGIFDSTADDR_ISO"); 1883 } 1884 (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1885 siso = &ifr.ifr_Addr; 1886 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 1887 } 1888 putchar('\n'); 1889 } 1890 1891 #endif /* INET_ONLY */ 1892 1893 struct in_addr inet_makeaddr(); 1894 1895 #define SIN(x) ((struct sockaddr_in *) &(x)) 1896 struct sockaddr_in *sintab[] = { 1897 SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 1898 SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 1899 1900 void 1901 in_getaddr(s, which) 1902 char *s; 1903 int which; 1904 { 1905 struct sockaddr_in *sin = sintab[which]; 1906 struct hostent *hp; 1907 struct netent *np; 1908 1909 sin->sin_len = sizeof(*sin); 1910 if (which != MASK) 1911 sin->sin_family = AF_INET; 1912 1913 if (inet_aton(s, &sin->sin_addr) == 0) { 1914 if ((hp = gethostbyname(s))) 1915 memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); 1916 else if ((np = getnetbyname(s))) 1917 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 1918 else 1919 errx(1, "%s: bad value", s); 1920 } 1921 } 1922 1923 void 1924 in_getprefix(plen, which) 1925 char *plen; 1926 int which; 1927 { 1928 struct sockaddr_in *sin = sintab[which]; 1929 u_char *cp; 1930 int len = strtol(plen, (char **)NULL, 10); 1931 1932 if ((len < 0) || (len > 32)) 1933 errx(1, "%s: bad value", plen); 1934 sin->sin_len = sizeof(*sin); 1935 if (which != MASK) 1936 sin->sin_family = AF_INET; 1937 if ((len == 0) || (len == 32)) { 1938 memset(&sin->sin_addr, 0xff, sizeof(struct in_addr)); 1939 return; 1940 } 1941 memset((void *)&sin->sin_addr, 0x00, sizeof(sin->sin_addr)); 1942 for (cp = (u_char *)&sin->sin_addr; len > 7; len -= 8) 1943 *cp++ = 0xff; 1944 if (len) 1945 *cp = 0xff << (8 - len); 1946 } 1947 1948 /* 1949 * Print a value a la the %b format of the kernel's printf 1950 */ 1951 void 1952 printb(s, v, bits) 1953 char *s; 1954 char *bits; 1955 unsigned short v; 1956 { 1957 int i, any = 0; 1958 char c; 1959 1960 if (bits && *bits == 8) 1961 printf("%s=%o", s, v); 1962 else 1963 printf("%s=%x", s, v); 1964 bits++; 1965 if (bits) { 1966 putchar('<'); 1967 while ((i = *bits++)) { 1968 if (v & (1 << (i-1))) { 1969 if (any) 1970 putchar(','); 1971 any = 1; 1972 for (; (c = *bits) > 32; bits++) 1973 putchar(c); 1974 } else 1975 for (; *bits > 32; bits++) 1976 ; 1977 } 1978 putchar('>'); 1979 } 1980 } 1981 1982 #ifdef INET6 1983 #define SIN6(x) ((struct sockaddr_in6 *) &(x)) 1984 struct sockaddr_in6 *sin6tab[] = { 1985 SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 1986 SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 1987 1988 void 1989 in6_getaddr(s, which) 1990 char *s; 1991 int which; 1992 { 1993 #ifndef KAME_SCOPEID 1994 struct sockaddr_in6 *sin6 = sin6tab[which]; 1995 1996 sin->sin6_len = sizeof(*sin6); 1997 if (which != MASK) 1998 sin6->sin6_family = AF_INET6; 1999 2000 if (inet_pton(AF_INET6, s, &sin6->sin6_addr) != 1) 2001 errx(1, "%s: bad value", s); 2002 #else 2003 struct sockaddr_in6 *sin6 = sin6tab[which]; 2004 struct addrinfo hints, *res; 2005 int error; 2006 2007 memset(&hints, 0, sizeof(hints)); 2008 hints.ai_family = AF_INET6; 2009 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 2010 error = getaddrinfo(s, "0", &hints, &res); 2011 if (error) 2012 errx(1, "%s: %s", s, gai_strerror(error)); 2013 if (res->ai_addrlen != sizeof(struct sockaddr_in6)) 2014 errx(1, "%s: bad value", s); 2015 memcpy(sin6, res->ai_addr, res->ai_addrlen); 2016 #ifdef __KAME__ 2017 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 2018 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] == 0 && 2019 sin6->sin6_scope_id) { 2020 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] = 2021 htons(sin6->sin6_scope_id & 0xffff); 2022 sin6->sin6_scope_id = 0; 2023 } 2024 #endif 2025 freeaddrinfo(res); 2026 #endif 2027 } 2028 2029 void 2030 in6_getprefix(plen, which) 2031 char *plen; 2032 int which; 2033 { 2034 struct sockaddr_in6 *sin = sin6tab[which]; 2035 u_char *cp; 2036 int len = strtol(plen, (char **)NULL, 10); 2037 2038 if ((len < 0) || (len > 128)) 2039 errx(1, "%s: bad value", plen); 2040 sin->sin6_len = sizeof(*sin); 2041 if (which != MASK) 2042 sin->sin6_family = AF_INET6; 2043 if ((len == 0) || (len == 128)) { 2044 memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); 2045 return; 2046 } 2047 memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); 2048 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 2049 *cp++ = 0xff; 2050 if (len) 2051 *cp = 0xff << (8 - len); 2052 } 2053 2054 int 2055 prefix(val, size) 2056 void *val; 2057 int size; 2058 { 2059 u_char *name = (u_char *)val; 2060 int byte, bit, plen = 0; 2061 2062 for (byte = 0; byte < size; byte++, plen += 8) 2063 if (name[byte] != 0xff) 2064 break; 2065 if (byte == size) 2066 return (plen); 2067 for (bit = 7; bit != 0; bit--, plen++) 2068 if (!(name[byte] & (1 << bit))) 2069 break; 2070 for (; bit != 0; bit--) 2071 if (name[byte] & (1 << bit)) 2072 return(0); 2073 byte++; 2074 for (; byte < size; byte++) 2075 if (name[byte]) 2076 return(0); 2077 return (plen); 2078 } 2079 #endif /*INET6*/ 2080 2081 #ifndef INET_ONLY 2082 void 2083 at_getaddr(addr, which) 2084 char *addr; 2085 int which; 2086 { 2087 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 2088 u_int net, node; 2089 2090 sat->sat_family = AF_APPLETALK; 2091 sat->sat_len = sizeof(*sat); 2092 if (which == MASK) 2093 errx(1, "AppleTalk does not use netmasks"); 2094 if (sscanf(addr, "%u.%u", &net, &node) != 2 || 2095 net == 0 || net > 0xffff || node == 0 || node > 0xfe) 2096 errx(1, "%s: illegal address", addr); 2097 sat->sat_addr.s_net = htons(net); 2098 sat->sat_addr.s_node = node; 2099 } 2100 2101 void 2102 setatrange(range, d) 2103 char *range; 2104 int d; 2105 { 2106 u_short first = 123, last = 123; 2107 2108 if (sscanf(range, "%hu-%hu", &first, &last) != 2 || 2109 first == 0 || first > 0xffff || 2110 last == 0 || last > 0xffff || first > last) 2111 errx(1, "%s: illegal net range: %u-%u", range, first, last); 2112 at_nr.nr_firstnet = htons(first); 2113 at_nr.nr_lastnet = htons(last); 2114 } 2115 2116 void 2117 setatphase(phase, d) 2118 char *phase; 2119 int d; 2120 { 2121 if (!strcmp(phase, "1")) 2122 at_nr.nr_phase = 1; 2123 else if (!strcmp(phase, "2")) 2124 at_nr.nr_phase = 2; 2125 else 2126 errx(1, "%s: illegal phase", phase); 2127 } 2128 2129 void 2130 checkatrange(sat) 2131 struct sockaddr_at *sat; 2132 { 2133 if (at_nr.nr_phase == 0) 2134 at_nr.nr_phase = 2; /* Default phase 2 */ 2135 if (at_nr.nr_firstnet == 0) /* Default range of one */ 2136 at_nr.nr_firstnet = at_nr.nr_lastnet = sat->sat_addr.s_net; 2137 printf("\tatalk %d.%d range %d-%d phase %d\n", 2138 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 2139 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 2140 if ((u_short) ntohs(at_nr.nr_firstnet) > 2141 (u_short) ntohs(sat->sat_addr.s_net) || 2142 (u_short) ntohs(at_nr.nr_lastnet) < 2143 (u_short) ntohs(sat->sat_addr.s_net)) 2144 errx(1, "AppleTalk address is not in range"); 2145 *((struct netrange *) &sat->sat_zero) = at_nr; 2146 } 2147 2148 #define SNS(x) ((struct sockaddr_ns *) &(x)) 2149 struct sockaddr_ns *snstab[] = { 2150 SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 2151 SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 2152 2153 void 2154 xns_getaddr(addr, which) 2155 char *addr; 2156 int which; 2157 { 2158 struct sockaddr_ns *sns = snstab[which]; 2159 struct ns_addr ns_addr(); 2160 2161 sns->sns_family = AF_NS; 2162 sns->sns_len = sizeof(*sns); 2163 sns->sns_addr = ns_addr(addr); 2164 if (which == MASK) 2165 printf("Attempt to set XNS netmask will be ineffectual\n"); 2166 } 2167 2168 #define SIPX(x) ((struct sockaddr_ipx *) &(x)) 2169 struct sockaddr_ipx *sipxtab[] = { 2170 SIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr), 2171 SIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)}; 2172 2173 void 2174 ipx_getaddr(addr, which) 2175 char *addr; 2176 int which; 2177 { 2178 struct sockaddr_ipx *sipx = sipxtab[which]; 2179 struct ipx_addr ipx_addr(); 2180 2181 sipx->sipx_family = AF_IPX; 2182 sipx->sipx_len = sizeof(*sipx); 2183 sipx->sipx_addr = ipx_addr(addr); 2184 sipx->sipx_type = ipx_type; 2185 if (which == MASK) 2186 printf("Attempt to set IPX netmask will be ineffectual\n"); 2187 } 2188 2189 #define SISO(x) ((struct sockaddr_iso *) &(x)) 2190 struct sockaddr_iso *sisotab[] = { 2191 SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 2192 SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 2193 2194 void 2195 iso_getaddr(addr, which) 2196 char *addr; 2197 int which; 2198 { 2199 struct sockaddr_iso *siso = sisotab[which]; 2200 struct iso_addr *iso_addr(); 2201 siso->siso_addr = *iso_addr(addr); 2202 2203 if (which == MASK) { 2204 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 2205 siso->siso_nlen = 0; 2206 } else { 2207 siso->siso_len = sizeof(*siso); 2208 siso->siso_family = AF_ISO; 2209 } 2210 } 2211 2212 void 2213 setsnpaoffset(val) 2214 char *val; 2215 { 2216 iso_addreq.ifra_snpaoffset = atoi(val); 2217 } 2218 2219 void 2220 setnsellength(val) 2221 char *val; 2222 { 2223 nsellength = atoi(val); 2224 if (nsellength < 0) 2225 errx(1, "negative NSEL length is absurd"); 2226 if (afp == 0 || afp->af_af != AF_ISO) 2227 errx(1, "setting NSEL length valid only for iso"); 2228 } 2229 2230 void 2231 fixnsel(s) 2232 struct sockaddr_iso *s; 2233 { 2234 if (s->siso_family == 0) 2235 return; 2236 s->siso_tlen = nsellength; 2237 } 2238 2239 void 2240 adjust_nsellength() 2241 { 2242 fixnsel(sisotab[RIDADDR]); 2243 fixnsel(sisotab[ADDR]); 2244 fixnsel(sisotab[DSTADDR]); 2245 } 2246 2247 #endif /* INET_ONLY */ 2248 2249 void 2250 usage() 2251 { 2252 fprintf(stderr, "usage: ifconfig [ -m ] [ -a ] [ -A ] [ interface ]\n" 2253 "\t[ [af] [ address [ dest_addr ] ] [ up ] [ down ] " 2254 "[ netmask mask ] ]\n" 2255 "\t[media media_type] [mediaopt media_option]\n" 2256 "\t[ metric n ]\n" 2257 "\t[ mtu n ]\n" 2258 "\t[ nwid netword_id ]\n" 2259 "\t[ tunnel srcaddress dstaddress ]\n" 2260 "\t[ deletetunnel ]\n" 2261 "\t[ vlan n vlandev interface ]\n" 2262 "\t[ arp | -arp ]\n" 2263 "\t[ -802.2 | -802.3 | -802.2tr | -snap | -EtherII ]\n" 2264 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n" 2265 " ifconfig [-a | -A | -am | -Am] [ af ]\n" 2266 " ifconfig -m interface [af]\n"); 2267 exit(1); 2268 } 2269 2270 #ifndef INET_ONLY 2271 2272 static int __tag = 0; 2273 static int __have_tag = 0; 2274 2275 void vlan_status() 2276 { 2277 struct vlanreq vreq; 2278 2279 bzero((char *)&vreq, sizeof(struct vlanreq)); 2280 ifr.ifr_data = (caddr_t)&vreq; 2281 2282 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 2283 return; 2284 2285 if (vreq.vlr_tag || (vreq.vlr_parent[0] != '\0')) 2286 printf("\tvlan: %d parent interface: %s\n", 2287 vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ? 2288 "<none>" : vreq.vlr_parent); 2289 2290 return; 2291 } 2292 2293 void setvlantag(val, d) 2294 char *val; 2295 int d; 2296 { 2297 u_int16_t tag; 2298 struct vlanreq vreq; 2299 2300 __tag = tag = atoi(val); 2301 __have_tag = 1; 2302 2303 bzero((char *)&vreq, sizeof(struct vlanreq)); 2304 ifr.ifr_data = (caddr_t)&vreq; 2305 2306 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 2307 err(1, "SIOCGETVLAN"); 2308 2309 vreq.vlr_tag = tag; 2310 2311 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 2312 err(1, "SIOCSETVLAN"); 2313 2314 return; 2315 } 2316 2317 void setvlandev(val, d) 2318 char *val; 2319 int d; 2320 { 2321 struct vlanreq vreq; 2322 2323 if (!__have_tag) 2324 errx(1, "must specify both vlan tag and device"); 2325 2326 bzero((char *)&vreq, sizeof(struct vlanreq)); 2327 ifr.ifr_data = (caddr_t)&vreq; 2328 2329 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 2330 err(1, "SIOCGETVLAN"); 2331 2332 (void) strlcpy(vreq.vlr_parent, val, sizeof(vreq.vlr_parent)); 2333 vreq.vlr_tag = __tag; 2334 2335 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 2336 err(1, "SIOCSETVLAN"); 2337 2338 return; 2339 } 2340 2341 void unsetvlandev(val, d) 2342 char *val; 2343 int d; 2344 { 2345 struct vlanreq vreq; 2346 2347 bzero((char *)&vreq, sizeof(struct vlanreq)); 2348 ifr.ifr_data = (caddr_t)&vreq; 2349 2350 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 2351 err(1, "SIOCGETVLAN"); 2352 2353 bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent)); 2354 vreq.vlr_tag = 0; 2355 2356 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 2357 err(1, "SIOCSETVLAN"); 2358 2359 return; 2360 } 2361 2362 #endif /* INET_ONLY */ 2363 2364 #ifdef INET6 2365 char * 2366 sec2str(total) 2367 time_t total; 2368 { 2369 static char result[256]; 2370 int days, hours, mins, secs; 2371 int first = 1; 2372 char *p = result; 2373 char *end = &result[sizeof(result)]; 2374 int n; 2375 2376 if (0) { /*XXX*/ 2377 days = total / 3600 / 24; 2378 hours = (total / 3600) % 24; 2379 mins = (total / 60) % 60; 2380 secs = total % 60; 2381 2382 if (days) { 2383 first = 0; 2384 n = snprintf(p, end - p, "%dd", days); 2385 if (n < 0 || n >= end - p) 2386 return(result); 2387 p += n; 2388 } 2389 if (!first || hours) { 2390 first = 0; 2391 n = snprintf(p, end - p, "%dh", hours); 2392 if (n < 0 || n >= end - p) 2393 return(result); 2394 p += n; 2395 } 2396 if (!first || mins) { 2397 first = 0; 2398 n = snprintf(p, end - p, "%dm", mins); 2399 if (n < 0 || n >= end - p) 2400 return(result); 2401 p += n; 2402 } 2403 snprintf(p, end - p, "%ds", secs); 2404 } else 2405 snprintf(p, end - p, "%lu", (u_long)total); 2406 2407 return(result); 2408 } 2409 #endif 2410