ifconfig.c revision 1.116
1/* $NetBSD: ifconfig.c,v 1.116 2001/09/26 07:20:16 itojun Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 2000 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.116 2001/09/26 07:20:16 itojun 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 <net/if_ether.h> 95#include <net/if_ieee80211.h> 96#include <net/if_vlanvar.h> 97#include <netinet/in.h> 98#include <netinet/in_var.h> 99#ifdef INET6 100#include <netinet6/nd6.h> 101#endif 102#include <arpa/inet.h> 103 104#include <netatalk/at.h> 105 106#define NSIP 107#include <netns/ns.h> 108#include <netns/ns_if.h> 109#include <netdb.h> 110 111#define EON 112#include <netiso/iso.h> 113#include <netiso/iso_var.h> 114#include <sys/protosw.h> 115 116#include <ctype.h> 117#include <err.h> 118#include <errno.h> 119#include <stddef.h> 120#include <stdio.h> 121#include <stdlib.h> 122#include <string.h> 123#include <unistd.h> 124#include <ifaddrs.h> 125 126struct ifreq ifr, ridreq; 127struct ifaliasreq addreq __attribute__((aligned(4))); 128#ifdef INET6 129struct in6_ifreq ifr6; 130struct in6_ifreq in6_ridreq; 131struct in6_aliasreq in6_addreq __attribute__((aligned(4))); 132#endif 133struct iso_ifreq iso_ridreq; 134struct iso_aliasreq iso_addreq; 135struct sockaddr_in netmask; 136struct netrange at_nr; /* AppleTalk net range */ 137 138char name[30]; 139int flags, metric, mtu, setaddr, setipdst, doalias; 140int clearaddr, s; 141int newaddr = -1; 142int conflicting = 0; 143int nsellength = 1; 144int af; 145int aflag, bflag, Cflag, dflag, lflag, mflag, sflag, uflag; 146#ifdef INET6 147int Lflag; 148#endif 149int reset_if_flags; 150int explicit_prefix = 0; 151u_int vlan_tag = (u_int)-1; 152 153struct ifcapreq g_ifcr; 154int g_ifcr_updated; 155 156void notealias __P((const char *, int)); 157void notrailers __P((const char *, int)); 158void setifaddr __P((const char *, int)); 159void setifdstaddr __P((const char *, int)); 160void setifflags __P((const char *, int)); 161void setifcaps __P((const char *, int)); 162void setifbroadaddr __P((const char *, int)); 163void setifipdst __P((const char *, int)); 164void setifmetric __P((const char *, int)); 165void setifmtu __P((const char *, int)); 166void setifnwid __P((const char *, int)); 167void setifnwkey __P((const char *, int)); 168void setifpowersave __P((const char *, int)); 169void setifpowersavesleep __P((const char *, int)); 170void setifnetmask __P((const char *, int)); 171void setifprefixlen __P((const char *, int)); 172void setnsellength __P((const char *, int)); 173void setsnpaoffset __P((const char *, int)); 174void setatrange __P((const char *, int)); 175void setatphase __P((const char *, int)); 176void settunnel __P((const char *, const char *)); 177void deletetunnel __P((const char *, int)); 178#ifdef INET6 179void setia6flags __P((const char *, int)); 180void setia6pltime __P((const char *, int)); 181void setia6vltime __P((const char *, int)); 182void setia6lifetime __P((const char *, const char *)); 183#endif 184void checkatrange __P ((struct sockaddr_at *)); 185void setmedia __P((const char *, int)); 186void setmediaopt __P((const char *, int)); 187void unsetmediaopt __P((const char *, int)); 188void setmediainst __P((const char *, int)); 189void clone_create __P((const char *, int)); 190void clone_destroy __P((const char *, int)); 191void fixnsel __P((struct sockaddr_iso *)); 192void setvlan __P((const char *, int)); 193void setvlanif __P((const char *, int)); 194void unsetvlanif __P((const char *, int)); 195int main __P((int, char *[])); 196 197/* 198 * Media stuff. Whenever a media command is first performed, the 199 * currently select media is grabbed for this interface. If `media' 200 * is given, the current media word is modifed. `mediaopt' commands 201 * only modify the set and clear words. They then operate on the 202 * current media word later. 203 */ 204int media_current; 205int mediaopt_set; 206int mediaopt_clear; 207 208int actions; /* Actions performed */ 209 210#define A_MEDIA 0x0001 /* media command */ 211#define A_MEDIAOPTSET 0x0002 /* mediaopt command */ 212#define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */ 213#define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR) 214#define A_MEDIAINST 0x0008 /* instance or inst command */ 215 216#define NEXTARG 0xffffff 217#define NEXTARG2 0xfffffe 218 219const struct cmd { 220 const char *c_name; 221 int c_parameter; /* NEXTARG means next argv */ 222 int c_action; /* defered action */ 223 void (*c_func) __P((const char *, int)); 224 void (*c_func2) __P((const char *, const char *)); 225} cmds[] = { 226 { "up", IFF_UP, 0, setifflags } , 227 { "down", -IFF_UP, 0, setifflags }, 228 { "trailers", -1, 0, notrailers }, 229 { "-trailers", 1, 0, notrailers }, 230 { "arp", -IFF_NOARP, 0, setifflags }, 231 { "-arp", IFF_NOARP, 0, setifflags }, 232 { "debug", IFF_DEBUG, 0, setifflags }, 233 { "-debug", -IFF_DEBUG, 0, setifflags }, 234 { "alias", IFF_UP, 0, notealias }, 235 { "-alias", -IFF_UP, 0, notealias }, 236 { "delete", -IFF_UP, 0, notealias }, 237#ifdef notdef 238#define EN_SWABIPS 0x1000 239 { "swabips", EN_SWABIPS, 0, setifflags }, 240 { "-swabips", -EN_SWABIPS, 0, setifflags }, 241#endif 242 { "netmask", NEXTARG, 0, setifnetmask }, 243 { "metric", NEXTARG, 0, setifmetric }, 244 { "mtu", NEXTARG, 0, setifmtu }, 245 { "nwid", NEXTARG, 0, setifnwid }, 246 { "nwkey", NEXTARG, 0, setifnwkey }, 247 { "-nwkey", -1, 0, setifnwkey }, 248 { "powersave", 1, 0, setifpowersave }, 249 { "-powersave", 0, 0, setifpowersave }, 250 { "powersavesleep", NEXTARG, 0, setifpowersavesleep }, 251 { "broadcast", NEXTARG, 0, setifbroadaddr }, 252 { "ipdst", NEXTARG, 0, setifipdst }, 253 { "prefixlen", NEXTARG, 0, setifprefixlen}, 254#ifdef INET6 255 { "anycast", IN6_IFF_ANYCAST, 0, setia6flags }, 256 { "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags }, 257 { "tentative", IN6_IFF_TENTATIVE, 0, setia6flags }, 258 { "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags }, 259 { "deprecated", IN6_IFF_DEPRECATED, 0, setia6flags }, 260 { "-deprecated", -IN6_IFF_DEPRECATED, 0, setia6flags }, 261 { "pltime", NEXTARG, 0, setia6pltime }, 262 { "vltime", NEXTARG, 0, setia6vltime }, 263#endif /*INET6*/ 264#ifndef INET_ONLY 265 { "range", NEXTARG, 0, setatrange }, 266 { "phase", NEXTARG, 0, setatphase }, 267 { "snpaoffset", NEXTARG, 0, setsnpaoffset }, 268 { "nsellength", NEXTARG, 0, setnsellength }, 269#endif /* INET_ONLY */ 270 { "tunnel", NEXTARG2, 0, NULL, 271 settunnel } , 272 { "deletetunnel", 0, 0, deletetunnel }, 273 { "vlan", NEXTARG, 0, setvlan } , 274 { "vlanif", NEXTARG, 0, setvlanif } , 275 { "-vlanif", 0, 0, unsetvlanif } , 276#if 0 277 /* XXX `create' special-cased below */ 278 { "create", 0, 0, clone_create } , 279#endif 280 { "destroy", 0, 0, clone_destroy } , 281 { "link0", IFF_LINK0, 0, setifflags } , 282 { "-link0", -IFF_LINK0, 0, setifflags } , 283 { "link1", IFF_LINK1, 0, setifflags } , 284 { "-link1", -IFF_LINK1, 0, setifflags } , 285 { "link2", IFF_LINK2, 0, setifflags } , 286 { "-link2", -IFF_LINK2, 0, setifflags } , 287 { "media", NEXTARG, A_MEDIA, setmedia }, 288 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt }, 289 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt }, 290 { "instance", NEXTARG, A_MEDIAINST, setmediainst }, 291 { "inst", NEXTARG, A_MEDIAINST, setmediainst }, 292 { "ip4csum", IFCAP_CSUM_IPv4,0, setifcaps }, 293 { "-ip4csum", -IFCAP_CSUM_IPv4,0, setifcaps }, 294 { "tcp4csum", IFCAP_CSUM_TCPv4,0, setifcaps }, 295 { "-tcp4csum", -IFCAP_CSUM_TCPv4,0, setifcaps }, 296 { "udp4csum", IFCAP_CSUM_UDPv4,0, setifcaps }, 297 { "-udp4csum", -IFCAP_CSUM_UDPv4,0, setifcaps }, 298 { "tcp6csum", IFCAP_CSUM_TCPv6,0, setifcaps }, 299 { "-tcp6csum", -IFCAP_CSUM_TCPv6,0, setifcaps }, 300 { "udp6csum", IFCAP_CSUM_UDPv6,0, setifcaps }, 301 { "-udp6csum", -IFCAP_CSUM_UDPv6,0, setifcaps }, 302 { "tcp4csum-rx",IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 303 { "-tcp4csum-rx",-IFCAP_CSUM_TCPv4_Rx,0, setifcaps }, 304 { "udp4csum-rx",IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 305 { "-udp4csum-rx",-IFCAP_CSUM_UDPv4_Rx,0, setifcaps }, 306 { 0, 0, 0, setifaddr }, 307 { 0, 0, 0, setifdstaddr }, 308}; 309 310void adjust_nsellength __P((void)); 311int getinfo __P((struct ifreq *)); 312int carrier __P((void)); 313void getsock __P((int)); 314void printall __P((const char *)); 315void list_cloners __P((void)); 316void printb __P((const char *, unsigned short, const char *)); 317int prefix __P((void *, int)); 318void status __P((const u_int8_t *, int)); 319void usage __P((void)); 320const char *get_string __P((const char *, const char *, u_int8_t *, int *)); 321void print_string __P((const u_int8_t *, int)); 322char *sec2str __P((time_t)); 323 324const char *get_media_type_string __P((int)); 325const char *get_media_subtype_string __P((int)); 326int get_media_subtype __P((int, const char *)); 327int get_media_options __P((int, const char *)); 328int lookup_media_word __P((struct ifmedia_description *, int, 329 const char *)); 330void print_media_word __P((int, int, int)); 331void process_media_commands __P((void)); 332void init_current_media __P((void)); 333 334/* 335 * XNS support liberally adapted from code written at the University of 336 * Maryland principally by James O'Toole and Chris Torek. 337 */ 338void in_alias __P((struct ifreq *)); 339void in_status __P((int)); 340void in_getaddr __P((const char *, int)); 341void in_getprefix __P((const char *, int)); 342#ifdef INET6 343void in6_fillscopeid __P((struct sockaddr_in6 *sin6)); 344void in6_alias __P((struct in6_ifreq *)); 345void in6_status __P((int)); 346void in6_getaddr __P((const char *, int)); 347void in6_getprefix __P((const char *, int)); 348#endif 349void at_status __P((int)); 350void at_getaddr __P((const char *, int)); 351void xns_status __P((int)); 352void xns_getaddr __P((const char *, int)); 353void iso_status __P((int)); 354void iso_getaddr __P((const char *, int)); 355 356void ieee80211_status __P((void)); 357void tunnel_status __P((void)); 358void vlan_status __P((void)); 359 360/* Known address families */ 361struct afswtch { 362 const char *af_name; 363 short af_af; 364 void (*af_status) __P((int)); 365 void (*af_getaddr) __P((const char *, int)); 366 void (*af_getprefix) __P((const char *, int)); 367 u_long af_difaddr; 368 u_long af_aifaddr; 369 u_long af_gifaddr; 370 caddr_t af_ridreq; 371 caddr_t af_addreq; 372} afs[] = { 373#define C(x) ((caddr_t) &x) 374 { "inet", AF_INET, in_status, in_getaddr, in_getprefix, 375 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, C(ridreq), C(addreq) }, 376#ifdef INET6 377 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 378 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, 379 /* 380 * Deleting the first address before setting new one is 381 * not prefered way in this protocol. 382 */ 383 0, 384 C(in6_ridreq), C(in6_addreq) }, 385#endif 386#ifndef INET_ONLY /* small version, for boot media */ 387 { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL, 388 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, C(addreq), C(addreq) }, 389 { "ns", AF_NS, xns_status, xns_getaddr, NULL, 390 SIOCDIFADDR, SIOCAIFADDR, SIOCGIFADDR, C(ridreq), C(addreq) }, 391 { "iso", AF_ISO, iso_status, iso_getaddr, NULL, 392 SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, SIOCGIFADDR_ISO, 393 C(iso_ridreq), C(iso_addreq) }, 394#endif /* INET_ONLY */ 395 { 0, 0, 0, 0 } 396}; 397 398struct afswtch *afp; /*the address family being set or asked about*/ 399 400struct afswtch *lookup_af __P((const char *)); 401 402int 403main(argc, argv) 404 int argc; 405 char *argv[]; 406{ 407 struct ifreq ifreq; 408 int ch; 409 410 /* Parse command-line options */ 411 aflag = mflag = 0; 412 while ((ch = getopt(argc, argv, "AabCdlmsu" 413#ifdef INET6 414 "L" 415#endif 416 )) != -1) { 417 switch (ch) { 418 case 'A': 419 warnx("-A is deprecated"); 420 break; 421 422 case 'a': 423 aflag = 1; 424 break; 425 426 case 'b': 427 bflag = 1; 428 break; 429 430 431 case 'C': 432 Cflag = 1; 433 break; 434 435 case 'd': 436 dflag = 1; 437 break; 438 439#ifdef INET6 440 case 'L': 441 Lflag = 1; 442 break; 443#endif 444 445 case 'l': 446 lflag = 1; 447 break; 448 449 case 'm': 450 mflag = 1; 451 break; 452 453 case 's': 454 sflag = 1; 455 break; 456 457 case 'u': 458 uflag = 1; 459 break; 460 461 462 default: 463 usage(); 464 /* NOTREACHED */ 465 } 466 } 467 argc -= optind; 468 argv += optind; 469 470 /* 471 * -l means "list all interfaces", and is mutally exclusive with 472 * all other flags/commands. 473 * 474 * -C means "list all names of cloners", and it mutually exclusive 475 * with all other flags/commands. 476 * 477 * -a means "print status of all interfaces". 478 */ 479 if ((lflag || Cflag) && (aflag || mflag || argc)) 480 usage(); 481#ifdef INET6 482 if ((lflag || Cflag) && Lflag) 483 usage(); 484#endif 485 if (lflag && Cflag) 486 usage(); 487 if (Cflag) { 488 if (argc) 489 usage(); 490 list_cloners(); 491 exit(0); 492 } 493 if (aflag || lflag) { 494 if (argc > 1) 495 usage(); 496 else if (argc == 1) { 497 afp = lookup_af(argv[0]); 498 if (afp == NULL) 499 usage(); 500 } 501 if (afp) 502 af = ifr.ifr_addr.sa_family = afp->af_af; 503 else 504 af = ifr.ifr_addr.sa_family = afs[0].af_af; 505 printall(NULL); 506 exit(0); 507 } 508 509 /* Make sure there's an interface name. */ 510 if (argc < 1) 511 usage(); 512 (void) strncpy(name, argv[0], sizeof(name)); 513 argc--; argv++; 514 515 /* 516 * NOTE: We must special-case the `create' command right 517 * here as we would otherwise fail in getinfo(). 518 */ 519 if (argc > 0 && strcmp(argv[0], "create") == 0) { 520 clone_create(argv[0], 0); 521 argc--, argv++; 522 if (argc == 0) 523 exit(0); 524 } 525 526 /* Check for address family. */ 527 afp = NULL; 528 if (argc > 0) { 529 afp = lookup_af(argv[0]); 530 if (afp != NULL) { 531 argv++; 532 argc--; 533 } 534 } 535 536 /* Initialize af, just for use in getinfo(). */ 537 if (afp == NULL) 538 af = afs->af_af; 539 else 540 af = afp->af_af; 541 542 /* Get information about the interface. */ 543 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 544 if (getinfo(&ifr) < 0) 545 exit(1); 546 547 if (sflag) { 548 if (argc != 0) 549 usage(); 550 else 551 exit(carrier()); 552 } 553 554 /* No more arguments means interface status. */ 555 if (argc == 0) { 556 printall(name); 557 exit(0); 558 } 559 560 /* The following operations assume inet family as the default. */ 561 if (afp == NULL) 562 afp = afs; 563 af = ifr.ifr_addr.sa_family = afp->af_af; 564 565#ifdef INET6 566 /* initialization */ 567 in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 568 in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 569#endif 570 571 /* Process commands. */ 572 while (argc > 0) { 573 const struct cmd *p; 574 575 for (p = cmds; p->c_name; p++) 576 if (strcmp(argv[0], p->c_name) == 0) 577 break; 578 if (p->c_name == 0 && setaddr) { 579 if ((flags & IFF_POINTOPOINT) == 0) { 580 errx(1, "can't set destination address %s", 581 "on non-point-to-point link"); 582 } 583 p++; /* got src, do dst */ 584 } 585 if (p->c_func != NULL || p->c_func2 != NULL) { 586 if (p->c_parameter == NEXTARG) { 587 if (argc < 2) 588 errx(1, "'%s' requires argument", 589 p->c_name); 590 (*p->c_func)(argv[1], 0); 591 argc--, argv++; 592 } else if (p->c_parameter == NEXTARG2) { 593 if (argc < 3) 594 errx(1, "'%s' requires 2 arguments", 595 p->c_name); 596 (*p->c_func2)(argv[1], argv[2]); 597 argc -= 2, argv += 2; 598 } else 599 (*p->c_func)(argv[0], p->c_parameter); 600 actions |= p->c_action; 601 } 602 argc--, argv++; 603 } 604 605 /* 606 * See if multiple alias, -alias, or delete commands were 607 * specified. More than one constitutes an invalid command line 608 */ 609 610 if (conflicting > 1) 611 err(1, "Only one use of alias, -alias or delete is valid."); 612 613 /* Process any media commands that may have been issued. */ 614 process_media_commands(); 615 616 if (af == AF_INET6 && explicit_prefix == 0) { 617 /* 618 * Aggregatable address architecture defines all prefixes 619 * are 64. So, it is convenient to set prefixlen to 64 if 620 * it is not specified. 621 */ 622 setifprefixlen("64", 0); 623 /* in6_getprefix("64", MASK) if MASK is available here... */ 624 } 625 626#ifndef INET_ONLY 627 if (af == AF_ISO) 628 adjust_nsellength(); 629 630 if (af == AF_APPLETALK) 631 checkatrange((struct sockaddr_at *) &addreq.ifra_addr); 632 633 if (setipdst && af==AF_NS) { 634 struct nsip_req rq; 635 int size = sizeof(rq); 636 637 rq.rq_ns = addreq.ifra_addr; 638 rq.rq_ip = addreq.ifra_dstaddr; 639 640 if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0) 641 warn("encapsulation routing"); 642 } 643 644#endif /* INET_ONLY */ 645 646 if (clearaddr) { 647 (void) strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); 648 if (ioctl(s, afp->af_difaddr, afp->af_ridreq) < 0) 649 err(1, "SIOCDIFADDR"); 650 } 651 if (newaddr > 0) { 652 (void) strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); 653 if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) 654 warn("SIOCAIFADDR"); 655 } 656 657 if (g_ifcr_updated) { 658 (void) strncpy(g_ifcr.ifcr_name, name, 659 sizeof(g_ifcr.ifcr_name)); 660 if (ioctl(s, SIOCSIFCAP, (caddr_t) &g_ifcr) < 0) 661 err(1, "SIOCSIFCAP"); 662 } 663 664 if (reset_if_flags) { 665 (void) strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); 666 ifreq.ifr_flags = flags; 667 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifreq) < 0) 668 err(1, "SIOCSIFFLAGS"); 669 } 670 exit(0); 671} 672 673struct afswtch * 674lookup_af(cp) 675 const char *cp; 676{ 677 struct afswtch *a; 678 679 for (a = afs; a->af_name != NULL; a++) 680 if (strcmp(a->af_name, cp) == 0) 681 return (a); 682 return (NULL); 683} 684 685void 686getsock(naf) 687 int naf; 688{ 689 static int oaf = -1; 690 691 if (oaf == naf) 692 return; 693 if (oaf != -1) 694 close(s); 695 s = socket(naf, SOCK_DGRAM, 0); 696 if (s < 0) 697 oaf = -1; 698 else 699 oaf = naf; 700} 701 702int 703getinfo(ifr) 704 struct ifreq *ifr; 705{ 706 707 getsock(af); 708 if (s < 0) 709 err(1, "socket"); 710 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)ifr) < 0) { 711 warn("SIOCGIFFLAGS %s", ifr->ifr_name); 712 return (-1); 713 } 714 flags = ifr->ifr_flags; 715 if (ioctl(s, SIOCGIFMETRIC, (caddr_t)ifr) < 0) { 716 warn("SIOCGIFMETRIC %s", ifr->ifr_name); 717 metric = 0; 718 } else 719 metric = ifr->ifr_metric; 720 if (ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) 721 mtu = 0; 722 else 723 mtu = ifr->ifr_mtu; 724 725 memset(&g_ifcr, 0, sizeof(g_ifcr)); 726 strcpy(g_ifcr.ifcr_name, ifr->ifr_name); 727 (void) ioctl(s, SIOCGIFCAP, (caddr_t) &g_ifcr); 728 729 return (0); 730} 731 732void 733printall(ifname) 734 const char *ifname; 735{ 736 struct ifaddrs *ifap, *ifa; 737 struct ifreq ifr; 738 const struct sockaddr_dl *sdl = NULL; 739 int idx; 740 char *p; 741 742 if (getifaddrs(&ifap) != 0) 743 err(1, "getifaddrs"); 744 p = NULL; 745 idx = 0; 746 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 747 memset(&ifr, 0, sizeof(ifr)); 748 strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); 749 if (sizeof(ifr.ifr_addr) >= ifa->ifa_addr->sa_len) { 750 memcpy(&ifr.ifr_addr, ifa->ifa_addr, 751 ifa->ifa_addr->sa_len); 752 } 753 754 if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 755 continue; 756 if (ifa->ifa_addr->sa_family == AF_LINK) 757 sdl = (const struct sockaddr_dl *) ifa->ifa_addr; 758 if (p && strcmp(p, ifa->ifa_name) == 0) 759 continue; 760 (void) strncpy(name, ifa->ifa_name, sizeof(name)); 761 name[sizeof(name) - 1] = '\0'; 762 p = ifa->ifa_name; 763 764 if (getinfo(&ifr) < 0) 765 continue; 766 if (bflag && (ifa->ifa_flags & (IFF_POINTOPOINT|IFF_LOOPBACK))) 767 continue; 768 if (dflag && (ifa->ifa_flags & IFF_UP) != 0) 769 continue; 770 if (uflag && (ifa->ifa_flags & IFF_UP) == 0) 771 continue; 772 773 if (sflag && carrier()) 774 continue; 775 idx++; 776 /* 777 * Are we just listing the interfaces? 778 */ 779 if (lflag) { 780 if (idx > 1) 781 putchar(' '); 782 fputs(name, stdout); 783 continue; 784 } 785 786 if (sdl == NULL) { 787 status(NULL, 0); 788 } else { 789 status(LLADDR(sdl), sdl->sdl_alen); 790 sdl = NULL; 791 } 792 } 793 if (lflag) 794 putchar('\n'); 795 freeifaddrs(ifap); 796} 797 798void 799list_cloners(void) 800{ 801 struct if_clonereq ifcr; 802 char *cp, *buf; 803 int idx; 804 805 memset(&ifcr, 0, sizeof(ifcr)); 806 807 getsock(AF_INET); 808 809 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 810 err(1, "SIOCIFGCLONERS for count"); 811 812 buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 813 if (buf == NULL) 814 err(1, "unable to allocate cloner name buffer"); 815 816 ifcr.ifcr_count = ifcr.ifcr_total; 817 ifcr.ifcr_buffer = buf; 818 819 if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0) 820 err(1, "SIOCIFGCLONERS for names"); 821 822 /* 823 * In case some disappeared in the mean time, clamp it down. 824 */ 825 if (ifcr.ifcr_count > ifcr.ifcr_total) 826 ifcr.ifcr_count = ifcr.ifcr_total; 827 828 for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 829 if (idx > 0) 830 putchar(' '); 831 printf("%s", cp); 832 } 833 834 putchar('\n'); 835 free(buf); 836 return; 837} 838 839/*ARGSUSED*/ 840void 841clone_create(addr, param) 842 const char *addr; 843 int param; 844{ 845 846 /* We're called early... */ 847 getsock(AF_INET); 848 849 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 850 if (ioctl(s, SIOCIFCREATE, &ifr) < 0) 851 err(1, "SIOCIFCREATE"); 852} 853 854/*ARGSUSED*/ 855void 856clone_destroy(addr, param) 857 const char *addr; 858 int param; 859{ 860 861 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 862 if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) 863 err(1, "SIOCIFDESTROY"); 864} 865 866#define RIDADDR 0 867#define ADDR 1 868#define MASK 2 869#define DSTADDR 3 870 871/*ARGSUSED*/ 872void 873setifaddr(addr, param) 874 const char *addr; 875 int param; 876{ 877 struct ifreq *ifr; /* XXX */ 878 879 /* 880 * Delay the ioctl to set the interface addr until flags are all set. 881 * The address interpretation may depend on the flags, 882 * and the flags may change when the address is set. 883 */ 884 setaddr++; 885 if (newaddr == -1) 886 newaddr = 1; 887 if (doalias == 0 && afp->af_gifaddr != 0) { 888 ifr = (struct ifreq *)afp->af_ridreq; 889 (void) strncpy(ifr->ifr_name, name, sizeof(ifr->ifr_name)); 890 ifr->ifr_addr.sa_family = afp->af_af; 891 if (ioctl(s, afp->af_gifaddr, afp->af_ridreq) == 0) 892 clearaddr = 1; 893 else if (errno == EADDRNOTAVAIL) 894 /* No address was assigned yet. */ 895 ; 896 else 897 err(1, "SIOCGIFADDR"); 898 } 899 900 (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); 901} 902 903void 904settunnel(src, dst) 905 const char *src, *dst; 906{ 907 struct addrinfo hints, *srcres, *dstres; 908 int ecode; 909 struct if_laddrreq req; 910 911 memset(&hints, 0, sizeof(hints)); 912 hints.ai_family = afp->af_af; 913 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 914 915 if ((ecode = getaddrinfo(src, NULL, &hints, &srcres)) != 0) 916 errx(1, "error in parsing address string: %s", 917 gai_strerror(ecode)); 918 919 if ((ecode = getaddrinfo(dst, NULL, &hints, &dstres)) != 0) 920 errx(1, "error in parsing address string: %s", 921 gai_strerror(ecode)); 922 923 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 924 errx(1, 925 "source and destination address families do not match"); 926 927 if (srcres->ai_addrlen > sizeof(req.addr) || 928 dstres->ai_addrlen > sizeof(req.dstaddr)) 929 errx(1, "invalid sockaddr"); 930 931 memset(&req, 0, sizeof(req)); 932 strncpy(req.iflr_name, name, sizeof(req.iflr_name)); 933 memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); 934 memcpy(&req.dstaddr, dstres->ai_addr, dstres->ai_addrlen); 935 936#ifdef INET6 937 if (req.addr.ss_family == AF_INET6) { 938 struct sockaddr_in6 *s, *d; 939 940 s = (struct sockaddr_in6 *)&req.addr; 941 d = (struct sockaddr_in6 *)&req.dstaddr; 942 if (s->sin6_scope_id != d->sin6_scope_id) { 943 errx(1, "scope mismatch"); 944 /* NOTREACHED */ 945 } 946#ifdef __KAME__ 947 /* embed scopeid */ 948 if (s->sin6_scope_id && 949 (IN6_IS_ADDR_LINKLOCAL(&s->sin6_addr) || 950 IN6_IS_ADDR_MC_LINKLOCAL(&s->sin6_addr))) { 951 *(u_int16_t *)&s->sin6_addr.s6_addr[2] = 952 htons(s->sin6_scope_id); 953 } 954 if (d->sin6_scope_id && 955 (IN6_IS_ADDR_LINKLOCAL(&d->sin6_addr) || 956 IN6_IS_ADDR_MC_LINKLOCAL(&d->sin6_addr))) { 957 *(u_int16_t *)&d->sin6_addr.s6_addr[2] = 958 htons(d->sin6_scope_id); 959 } 960#endif 961 } 962#endif 963 964 if (ioctl(s, SIOCSLIFPHYADDR, &req) < 0) 965 warn("SIOCSLIFPHYADDR"); 966 967 freeaddrinfo(srcres); 968 freeaddrinfo(dstres); 969} 970 971/* ARGSUSED */ 972void 973deletetunnel(vname, param) 974 const char *vname; 975 int param; 976{ 977 978 if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0) 979 err(1, "SIOCDIFPHYADDR"); 980} 981 982void setvlan(val, d) 983 const char *val; 984 int d; 985{ 986 struct vlanreq vlr; 987 988 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 989 !isdigit(ifr.ifr_name[4])) 990 errx(EXIT_FAILURE, 991 "``vlan'' valid only with vlan(4) interfaces"); 992 993 vlan_tag = atoi(val); 994 995 memset(&vlr, 0, sizeof(vlr)); 996 ifr.ifr_data = (caddr_t)&vlr; 997 998 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 999 err(EXIT_FAILURE, "SIOCGETVLAN"); 1000 1001 vlr.vlr_tag = vlan_tag; 1002 1003 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 1004 err(EXIT_FAILURE, "SIOCSETVLAN"); 1005} 1006 1007void setvlanif(val, d) 1008 const char *val; 1009 int d; 1010{ 1011 struct vlanreq vlr; 1012 1013 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 1014 !isdigit(ifr.ifr_name[4])) 1015 errx(EXIT_FAILURE, 1016 "``vlanif'' valid only with vlan(4) interfaces"); 1017 1018 if (vlan_tag == (u_int)-1) 1019 errx(EXIT_FAILURE, 1020 "must specify both ``vlan'' and ``vlanif''"); 1021 1022 memset(&vlr, 0, sizeof(vlr)); 1023 ifr.ifr_data = (caddr_t)&vlr; 1024 1025 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 1026 err(EXIT_FAILURE, "SIOCGETVLAN"); 1027 1028 strlcpy(vlr.vlr_parent, val, sizeof(vlr.vlr_parent)); 1029 vlr.vlr_tag = vlan_tag; 1030 1031 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 1032 err(EXIT_FAILURE, "SIOCSETVLAN"); 1033} 1034 1035void unsetvlanif(val, d) 1036 const char *val; 1037 int d; 1038{ 1039 struct vlanreq vlr; 1040 1041 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 1042 !isdigit(ifr.ifr_name[4])) 1043 errx(EXIT_FAILURE, 1044 "``vlanif'' valid only with vlan(4) interfaces"); 1045 1046 memset(&vlr, 0, sizeof(vlr)); 1047 ifr.ifr_data = (caddr_t)&vlr; 1048 1049 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 1050 err(EXIT_FAILURE, "SIOCGETVLAN"); 1051 1052 vlr.vlr_parent[0] = '\0'; 1053 vlr.vlr_tag = 0; 1054 1055 if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) 1056 err(EXIT_FAILURE, "SIOCSETVLAN"); 1057} 1058 1059void 1060setifnetmask(addr, d) 1061 const char *addr; 1062 int d; 1063{ 1064 (*afp->af_getaddr)(addr, MASK); 1065} 1066 1067void 1068setifbroadaddr(addr, d) 1069 const char *addr; 1070 int d; 1071{ 1072 (*afp->af_getaddr)(addr, DSTADDR); 1073} 1074 1075void 1076setifipdst(addr, d) 1077 const char *addr; 1078 int d; 1079{ 1080 in_getaddr(addr, DSTADDR); 1081 setipdst++; 1082 clearaddr = 0; 1083 newaddr = 0; 1084} 1085 1086#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 1087/*ARGSUSED*/ 1088void 1089notealias(addr, param) 1090 const char *addr; 1091 int param; 1092{ 1093 if (setaddr && doalias == 0 && param < 0) 1094 (void) memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), 1095 rqtosa(af_addreq)->sa_len); 1096 doalias = param; 1097 if (param < 0) { 1098 clearaddr = 1; 1099 newaddr = 0; 1100 conflicting++; 1101 } else { 1102 clearaddr = 0; 1103 conflicting++; 1104 } 1105} 1106 1107/*ARGSUSED*/ 1108void 1109notrailers(vname, value) 1110 const char *vname; 1111 int value; 1112{ 1113 puts("Note: trailers are no longer sent, but always received"); 1114} 1115 1116/*ARGSUSED*/ 1117void 1118setifdstaddr(addr, param) 1119 const char *addr; 1120 int param; 1121{ 1122 (*afp->af_getaddr)(addr, DSTADDR); 1123} 1124 1125void 1126setifflags(vname, value) 1127 const char *vname; 1128 int value; 1129{ 1130 struct ifreq ifreq; 1131 1132 (void) strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name)); 1133 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifreq) < 0) 1134 err(1, "SIOCGIFFLAGS"); 1135 flags = ifreq.ifr_flags; 1136 1137 if (value < 0) { 1138 value = -value; 1139 flags &= ~value; 1140 } else 1141 flags |= value; 1142 ifreq.ifr_flags = flags; 1143 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifreq) < 0) 1144 err(1, "SIOCSIFFLAGS"); 1145 1146 reset_if_flags = 1; 1147} 1148 1149void 1150setifcaps(vname, value) 1151 const char *vname; 1152 int value; 1153{ 1154 1155 if (value < 0) { 1156 value = -value; 1157 g_ifcr.ifcr_capenable &= ~value; 1158 } else 1159 g_ifcr.ifcr_capenable |= value; 1160 1161 g_ifcr_updated = 1; 1162} 1163 1164#ifdef INET6 1165void 1166setia6flags(vname, value) 1167 const char *vname; 1168 int value; 1169{ 1170 if (value < 0) { 1171 value = -value; 1172 in6_addreq.ifra_flags &= ~value; 1173 } else 1174 in6_addreq.ifra_flags |= value; 1175} 1176 1177void 1178setia6pltime(val, d) 1179 const char *val; 1180 int d; 1181{ 1182 setia6lifetime("pltime", val); 1183} 1184 1185void 1186setia6vltime(val, d) 1187 const char *val; 1188 int d; 1189{ 1190 setia6lifetime("vltime", val); 1191} 1192 1193void 1194setia6lifetime(cmd, val) 1195 const char *cmd; 1196 const char *val; 1197{ 1198 time_t newval, t; 1199 char *ep; 1200 1201 t = time(NULL); 1202 newval = (time_t)strtoul(val, &ep, 0); 1203 if (val == ep) 1204 errx(1, "invalid %s", cmd); 1205 if (afp->af_af != AF_INET6) 1206 errx(1, "%s not allowed for the AF", cmd); 1207 if (strcmp(cmd, "vltime") == 0) { 1208 in6_addreq.ifra_lifetime.ia6t_expire = t + newval; 1209 in6_addreq.ifra_lifetime.ia6t_vltime = newval; 1210 } else if (strcmp(cmd, "pltime") == 0) { 1211 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; 1212 in6_addreq.ifra_lifetime.ia6t_pltime = newval; 1213 } 1214} 1215#endif 1216 1217void 1218setifmetric(val, d) 1219 const char *val; 1220 int d; 1221{ 1222 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 1223 ifr.ifr_metric = atoi(val); 1224 if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) 1225 warn("SIOCSIFMETRIC"); 1226} 1227 1228void 1229setifmtu(val, d) 1230 const char *val; 1231 int d; 1232{ 1233 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1234 ifr.ifr_mtu = atoi(val); 1235 if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) 1236 warn("SIOCSIFMTU"); 1237} 1238 1239const char * 1240get_string(val, sep, buf, lenp) 1241 const char *val, *sep; 1242 u_int8_t *buf; 1243 int *lenp; 1244{ 1245 int len; 1246 int hexstr; 1247 u_int8_t *p; 1248 1249 len = *lenp; 1250 p = buf; 1251 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); 1252 if (hexstr) 1253 val += 2; 1254 for (;;) { 1255 if (*val == '\0') 1256 break; 1257 if (sep != NULL && strchr(sep, *val) != NULL) { 1258 val++; 1259 break; 1260 } 1261 if (hexstr) { 1262 if (!isxdigit((u_char)val[0]) || 1263 !isxdigit((u_char)val[1])) { 1264 warnx("bad hexadecimal digits"); 1265 return NULL; 1266 } 1267 } 1268 if (p > buf + len) { 1269 if (hexstr) 1270 warnx("hexadecimal digits too long"); 1271 else 1272 warnx("strings too long"); 1273 return NULL; 1274 } 1275 if (hexstr) { 1276#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) 1277 *p++ = (tohex((u_char)val[0]) << 4) | 1278 tohex((u_char)val[1]); 1279#undef tohex 1280 val += 2; 1281 } else 1282 *p++ = *val++; 1283 } 1284 len = p - buf; 1285 if (len < *lenp) 1286 memset(p, 0, *lenp - len); 1287 *lenp = len; 1288 return val; 1289} 1290 1291void 1292print_string(buf, len) 1293 const u_int8_t *buf; 1294 int len; 1295{ 1296 int i; 1297 int hasspc; 1298 1299 i = 0; 1300 hasspc = 0; 1301 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { 1302 for (; i < len; i++) { 1303 if (!isprint(buf[i])) 1304 break; 1305 if (isspace(buf[i])) 1306 hasspc++; 1307 } 1308 } 1309 if (i == len) { 1310 if (hasspc || len == 0) 1311 printf("\"%.*s\"", len, buf); 1312 else 1313 printf("%.*s", len, buf); 1314 } else { 1315 printf("0x"); 1316 for (i = 0; i < len; i++) 1317 printf("%02x", buf[i]); 1318 } 1319} 1320 1321void 1322setifnwid(val, d) 1323 const char *val; 1324 int d; 1325{ 1326 struct ieee80211_nwid nwid; 1327 int len; 1328 1329 len = sizeof(nwid.i_nwid); 1330 if (get_string(val, NULL, nwid.i_nwid, &len) == NULL) 1331 return; 1332 nwid.i_len = len; 1333 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1334 ifr.ifr_data = (caddr_t)&nwid; 1335 if (ioctl(s, SIOCS80211NWID, (caddr_t)&ifr) < 0) 1336 warn("SIOCS80211NWID"); 1337} 1338 1339void 1340setifnwkey(val, d) 1341 const char *val; 1342 int d; 1343{ 1344 struct ieee80211_nwkey nwkey; 1345 int i; 1346 u_int8_t keybuf[IEEE80211_WEP_NKID][16]; 1347 1348 nwkey.i_wepon = IEEE80211_NWKEY_WEP; 1349 nwkey.i_defkid = 1; 1350 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1351 nwkey.i_key[i].i_keylen = sizeof(keybuf[i]); 1352 nwkey.i_key[i].i_keydat = keybuf[i]; 1353 } 1354 if (d != 0) { 1355 /* disable WEP encryption */ 1356 nwkey.i_wepon = 0; 1357 i = 0; 1358 } else if (strcasecmp("persist", val) == 0) { 1359 /* use all values from persistent memory */ 1360 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; 1361 nwkey.i_defkid = 0; 1362 for (i = 0; i < IEEE80211_WEP_NKID; i++) 1363 nwkey.i_key[i].i_keylen = -1; 1364 } else if (strncasecmp("persist:", val, 8) == 0) { 1365 val += 8; 1366 /* program keys in persistent memory */ 1367 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; 1368 goto set_nwkey; 1369 } else { 1370 set_nwkey: 1371 if (isdigit(val[0]) && val[1] == ':') { 1372 /* specifying a full set of four keys */ 1373 nwkey.i_defkid = val[0] - '0'; 1374 val += 2; 1375 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1376 val = get_string(val, ",", keybuf[i], 1377 &nwkey.i_key[i].i_keylen); 1378 if (val == NULL) 1379 return; 1380 } 1381 if (*val != '\0') { 1382 warnx("SIOCS80211NWKEY: too many keys."); 1383 return; 1384 } 1385 } else { 1386 val = get_string(val, NULL, keybuf[0], 1387 &nwkey.i_key[0].i_keylen); 1388 if (val == NULL) 1389 return; 1390 i = 1; 1391 } 1392 } 1393 for (; i < IEEE80211_WEP_NKID; i++) 1394 nwkey.i_key[i].i_keylen = 0; 1395 (void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name)); 1396 if (ioctl(s, SIOCS80211NWKEY, (caddr_t)&nwkey) < 0) 1397 warn("SIOCS80211NWKEY"); 1398} 1399 1400void 1401setifpowersave(val, d) 1402 const char *val; 1403 int d; 1404{ 1405 struct ieee80211_power power; 1406 1407 (void)strncpy(power.i_name, name, sizeof(power.i_name)); 1408 if (ioctl(s, SIOCG80211POWER, (caddr_t)&power) < 0) { 1409 warn("SIOCG80211POWER"); 1410 return; 1411 } 1412 1413 power.i_enabled = d; 1414 if (ioctl(s, SIOCS80211POWER, (caddr_t)&power) < 0) 1415 warn("SIOCS80211POWER"); 1416} 1417 1418void 1419setifpowersavesleep(val, d) 1420 const char *val; 1421 int d; 1422{ 1423 struct ieee80211_power power; 1424 1425 (void)strncpy(power.i_name, name, sizeof(power.i_name)); 1426 if (ioctl(s, SIOCG80211POWER, (caddr_t)&power) < 0) { 1427 warn("SIOCG80211POWER"); 1428 return; 1429 } 1430 1431 power.i_maxsleep = atoi(val); 1432 if (ioctl(s, SIOCS80211POWER, (caddr_t)&power) < 0) 1433 warn("SIOCS80211POWER"); 1434} 1435 1436void 1437ieee80211_status() 1438{ 1439 int i, nwkey_verbose; 1440 struct ieee80211_nwid nwid; 1441 struct ieee80211_nwkey nwkey; 1442 struct ieee80211_power power; 1443 u_int8_t keybuf[IEEE80211_WEP_NKID][16]; 1444 1445 memset(&ifr, 0, sizeof(ifr)); 1446 ifr.ifr_data = (caddr_t)&nwid; 1447 (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1448 if (ioctl(s, SIOCG80211NWID, (caddr_t)&ifr) != 0) 1449 return; 1450 if (nwid.i_len > IEEE80211_NWID_LEN) { 1451 warnx("SIOCG80211NWID: wrong length of nwid (%d)", nwid.i_len); 1452 return; 1453 } 1454 printf("\tnwid "); 1455 print_string(nwid.i_nwid, nwid.i_len); 1456 memset(&nwkey, 0, sizeof(nwkey)); 1457 (void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name)); 1458 /* show nwkey only when WEP is enabled */ 1459 if (ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey) != 0 || 1460 nwkey.i_wepon == 0) { 1461 printf("\n"); 1462 goto skip_wep; 1463 } 1464 1465 printf(" nwkey "); 1466 /* try to retrieve WEP keys */ 1467 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1468 nwkey.i_key[i].i_keydat = keybuf[i]; 1469 nwkey.i_key[i].i_keylen = sizeof(keybuf[i]); 1470 } 1471 if (ioctl(s, SIOCG80211NWKEY, (caddr_t)&nwkey) != 0) { 1472 printf("*****"); 1473 } else { 1474 nwkey_verbose = 0; 1475 /* check to see non default key or multiple keys defined */ 1476 if (nwkey.i_defkid != 1) { 1477 nwkey_verbose = 1; 1478 } else { 1479 for (i = 1; i < IEEE80211_WEP_NKID; i++) { 1480 if (nwkey.i_key[i].i_keylen != 0) { 1481 nwkey_verbose = 1; 1482 break; 1483 } 1484 } 1485 } 1486 /* check extra ambiguity with keywords */ 1487 if (!nwkey_verbose) { 1488 if (nwkey.i_key[0].i_keylen >= 2 && 1489 isdigit(nwkey.i_key[0].i_keydat[0]) && 1490 nwkey.i_key[0].i_keydat[1] == ':') 1491 nwkey_verbose = 1; 1492 else if (nwkey.i_key[0].i_keylen >= 7 && 1493 strncasecmp("persist", nwkey.i_key[0].i_keydat, 7) 1494 == 0) 1495 nwkey_verbose = 1; 1496 } 1497 if (nwkey_verbose) 1498 printf("%d:", nwkey.i_defkid); 1499 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1500 if (i > 0) 1501 printf(","); 1502 if (nwkey.i_key[i].i_keylen < 0) 1503 printf("persist"); 1504 else 1505 print_string(nwkey.i_key[i].i_keydat, 1506 nwkey.i_key[i].i_keylen); 1507 if (!nwkey_verbose) 1508 break; 1509 } 1510 } 1511 printf("\n"); 1512 1513 skip_wep: 1514 (void)strncpy(power.i_name, name, sizeof(power.i_name)); 1515 if (ioctl(s, SIOCG80211POWER, &power) != 0) 1516 return; 1517 printf("\tpowersave "); 1518 if (power.i_enabled) 1519 printf("on (%dms sleep)", power.i_maxsleep); 1520 else 1521 printf("off"); 1522 printf("\n"); 1523} 1524 1525void 1526init_current_media() 1527{ 1528 struct ifmediareq ifmr; 1529 1530 /* 1531 * If we have not yet done so, grab the currently-selected 1532 * media. 1533 */ 1534 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) { 1535 (void) memset(&ifmr, 0, sizeof(ifmr)); 1536 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1537 1538 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1539 /* 1540 * If we get E2BIG, the kernel is telling us 1541 * that there are more, so we can ignore it. 1542 */ 1543 if (errno != E2BIG) 1544 err(1, "SGIOCGIFMEDIA"); 1545 } 1546 1547 media_current = ifmr.ifm_current; 1548 } 1549 1550 /* Sanity. */ 1551 if (IFM_TYPE(media_current) == 0) 1552 errx(1, "%s: no link type?", name); 1553} 1554 1555void 1556process_media_commands() 1557{ 1558 1559 if ((actions & (A_MEDIA|A_MEDIAOPT)) == 0) { 1560 /* Nothing to do. */ 1561 return; 1562 } 1563 1564 /* 1565 * Media already set up, and commands sanity-checked. Set/clear 1566 * any options, and we're ready to go. 1567 */ 1568 media_current |= mediaopt_set; 1569 media_current &= ~mediaopt_clear; 1570 1571 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 1572 ifr.ifr_media = media_current; 1573 1574 if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) 1575 err(1, "SIOCSIFMEDIA"); 1576} 1577 1578void 1579setmedia(val, d) 1580 const char *val; 1581 int d; 1582{ 1583 int type, subtype, inst; 1584 1585 init_current_media(); 1586 1587 /* Only one media command may be given. */ 1588 if (actions & A_MEDIA) 1589 errx(1, "only one `media' command may be issued"); 1590 1591 /* Must not come after mediaopt commands */ 1592 if (actions & A_MEDIAOPT) 1593 errx(1, "may not issue `media' after `mediaopt' commands"); 1594 1595 /* 1596 * No need to check if `instance' has been issued; setmediainst() 1597 * craps out if `media' has not been specified. 1598 */ 1599 1600 type = IFM_TYPE(media_current); 1601 inst = IFM_INST(media_current); 1602 1603 /* Look up the subtype. */ 1604 subtype = get_media_subtype(type, val); 1605 1606 /* Build the new current media word. */ 1607 media_current = IFM_MAKEWORD(type, subtype, 0, inst); 1608 1609 /* Media will be set after other processing is complete. */ 1610} 1611 1612void 1613setmediaopt(val, d) 1614 const char *val; 1615 int d; 1616{ 1617 1618 init_current_media(); 1619 1620 /* Can only issue `mediaopt' once. */ 1621 if (actions & A_MEDIAOPTSET) 1622 errx(1, "only one `mediaopt' command may be issued"); 1623 1624 /* Can't issue `mediaopt' if `instance' has already been issued. */ 1625 if (actions & A_MEDIAINST) 1626 errx(1, "may not issue `mediaopt' after `instance'"); 1627 1628 mediaopt_set = get_media_options(IFM_TYPE(media_current), val); 1629 1630 /* Media will be set after other processing is complete. */ 1631} 1632 1633void 1634unsetmediaopt(val, d) 1635 const char *val; 1636 int d; 1637{ 1638 1639 init_current_media(); 1640 1641 /* Can only issue `-mediaopt' once. */ 1642 if (actions & A_MEDIAOPTCLR) 1643 errx(1, "only one `-mediaopt' command may be issued"); 1644 1645 /* May not issue `media' and `-mediaopt'. */ 1646 if (actions & A_MEDIA) 1647 errx(1, "may not issue both `media' and `-mediaopt'"); 1648 1649 /* 1650 * No need to check for A_MEDIAINST, since the test for A_MEDIA 1651 * implicitly checks for A_MEDIAINST. 1652 */ 1653 1654 mediaopt_clear = get_media_options(IFM_TYPE(media_current), val); 1655 1656 /* Media will be set after other processing is complete. */ 1657} 1658 1659void 1660setmediainst(val, d) 1661 const char *val; 1662 int d; 1663{ 1664 int type, subtype, options, inst; 1665 1666 init_current_media(); 1667 1668 /* Can only issue `instance' once. */ 1669 if (actions & A_MEDIAINST) 1670 errx(1, "only one `instance' command may be issued"); 1671 1672 /* Must have already specified `media' */ 1673 if ((actions & A_MEDIA) == 0) 1674 errx(1, "must specify `media' before `instance'"); 1675 1676 type = IFM_TYPE(media_current); 1677 subtype = IFM_SUBTYPE(media_current); 1678 options = IFM_OPTIONS(media_current); 1679 1680 inst = atoi(val); 1681 if (inst < 0 || inst > IFM_INST_MAX) 1682 errx(1, "invalid media instance: %s", val); 1683 1684 media_current = IFM_MAKEWORD(type, subtype, options, inst); 1685 1686 /* Media will be set after other processing is complete. */ 1687} 1688 1689struct ifmedia_description ifm_type_descriptions[] = 1690 IFM_TYPE_DESCRIPTIONS; 1691 1692struct ifmedia_description ifm_subtype_descriptions[] = 1693 IFM_SUBTYPE_DESCRIPTIONS; 1694 1695struct ifmedia_description ifm_option_descriptions[] = 1696 IFM_OPTION_DESCRIPTIONS; 1697 1698const char * 1699get_media_type_string(mword) 1700 int mword; 1701{ 1702 struct ifmedia_description *desc; 1703 1704 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; 1705 desc++) { 1706 if (IFM_TYPE(mword) == desc->ifmt_word) 1707 return (desc->ifmt_string); 1708 } 1709 return ("<unknown type>"); 1710} 1711 1712const char * 1713get_media_subtype_string(mword) 1714 int mword; 1715{ 1716 struct ifmedia_description *desc; 1717 1718 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL; 1719 desc++) { 1720 if (IFM_TYPE_MATCH(desc->ifmt_word, mword) && 1721 IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword)) 1722 return (desc->ifmt_string); 1723 } 1724 return ("<unknown subtype>"); 1725} 1726 1727int 1728get_media_subtype(type, val) 1729 int type; 1730 const char *val; 1731{ 1732 int rval; 1733 1734 rval = lookup_media_word(ifm_subtype_descriptions, type, val); 1735 if (rval == -1) 1736 errx(1, "unknown %s media subtype: %s", 1737 get_media_type_string(type), val); 1738 1739 return (rval); 1740} 1741 1742int 1743get_media_options(type, val) 1744 int type; 1745 const char *val; 1746{ 1747 char *optlist, *str; 1748 int option, rval = 0; 1749 1750 /* We muck with the string, so copy it. */ 1751 optlist = strdup(val); 1752 if (optlist == NULL) 1753 err(1, "strdup"); 1754 str = optlist; 1755 1756 /* 1757 * Look up the options in the user-provided comma-separated list. 1758 */ 1759 for (; (str = strtok(str, ",")) != NULL; str = NULL) { 1760 option = lookup_media_word(ifm_option_descriptions, type, str); 1761 if (option == -1) 1762 errx(1, "unknown %s media option: %s", 1763 get_media_type_string(type), str); 1764 rval |= IFM_OPTIONS(option); 1765 } 1766 1767 free(optlist); 1768 return (rval); 1769} 1770 1771int 1772lookup_media_word(desc, type, val) 1773 struct ifmedia_description *desc; 1774 int type; 1775 const char *val; 1776{ 1777 1778 for (; desc->ifmt_string != NULL; desc++) { 1779 if (IFM_TYPE_MATCH(desc->ifmt_word, type) && 1780 strcasecmp(desc->ifmt_string, val) == 0) 1781 return (desc->ifmt_word); 1782 } 1783 return (-1); 1784} 1785 1786void 1787print_media_word(ifmw, print_type, as_syntax) 1788 int ifmw, print_type, as_syntax; 1789{ 1790 struct ifmedia_description *desc; 1791 int seen_option = 0; 1792 1793 if (print_type) 1794 printf("%s ", get_media_type_string(ifmw)); 1795 printf("%s%s", as_syntax ? "media " : "", 1796 get_media_subtype_string(ifmw)); 1797 1798 /* Find options. */ 1799 for (desc = ifm_option_descriptions; desc->ifmt_string != NULL; 1800 desc++) { 1801 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) && 1802 (ifmw & IFM_OPTIONS(desc->ifmt_word)) != 0 && 1803 (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) { 1804 if (seen_option == 0) 1805 printf(" %s", as_syntax ? "mediaopt " : ""); 1806 printf("%s%s", seen_option ? "," : "", 1807 desc->ifmt_string); 1808 seen_option |= IFM_OPTIONS(desc->ifmt_word); 1809 } 1810 } 1811 if (IFM_INST(ifmw) != 0) 1812 printf(" instance %d", IFM_INST(ifmw)); 1813} 1814 1815int carrier() 1816{ 1817 struct ifmediareq ifmr; 1818 1819 (void) memset(&ifmr, 0, sizeof(ifmr)); 1820 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1821 1822 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1823 /* 1824 * Interface doesn't support SIOC{G,S}IFMEDIA; 1825 * assume ok. 1826 */ 1827 return 0; 1828 } 1829 if ((ifmr.ifm_status & IFM_AVALID) == 0) { 1830 /* 1831 * Interface doesn't report media-valid status. 1832 * assume ok. 1833 */ 1834 return 0; 1835 } 1836 /* otherwise, return ok for active, not-ok if not active. */ 1837 return !(ifmr.ifm_status & IFM_ACTIVE); 1838} 1839 1840 1841#define IFFBITS \ 1842"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ 1843\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" 1844 1845#define IFCAPBITS \ 1846"\020\1IP4CSUM\2TCP4CSUM\3UDP4CSUM\4TCP6CSUM\5UDP6CSUM\6TCP4CSUM_Rx\7UDP4CSUM_Rx" 1847 1848const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 1849 1850const struct ifmedia_status_description ifm_status_descriptions[] = 1851 IFM_STATUS_DESCRIPTIONS; 1852 1853/* 1854 * Print the status of the interface. If an address family was 1855 * specified, show it and it only; otherwise, show them all. 1856 */ 1857void 1858status(ap, alen) 1859 const u_int8_t *ap; 1860 int alen; 1861{ 1862 struct afswtch *p = afp; 1863 struct ifmediareq ifmr; 1864 int *media_list, i; 1865 1866 printf("%s: ", name); 1867 printb("flags", flags, IFFBITS); 1868 if (metric) 1869 printf(" metric %d", metric); 1870 if (mtu) 1871 printf(" mtu %d", mtu); 1872 putchar('\n'); 1873 1874 if (g_ifcr.ifcr_capabilities) { 1875 putchar('\t'); 1876 printb("capabilities", g_ifcr.ifcr_capabilities, IFCAPBITS); 1877 putchar('\n'); 1878 1879 putchar('\t'); 1880 printb("enabled", g_ifcr.ifcr_capenable, IFCAPBITS); 1881 putchar('\n'); 1882 } 1883 1884 ieee80211_status(); 1885 vlan_status(); 1886 tunnel_status(); 1887 1888 if (ap && alen > 0) { 1889 printf("\taddress:"); 1890 for (i = 0; i < alen; i++, ap++) 1891 printf("%c%02x", i > 0 ? ':' : ' ', *ap); 1892 putchar('\n'); 1893 } 1894 1895 (void) memset(&ifmr, 0, sizeof(ifmr)); 1896 (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); 1897 1898 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 1899 /* 1900 * Interface doesn't support SIOC{G,S}IFMEDIA. 1901 */ 1902 goto proto_status; 1903 } 1904 1905 if (ifmr.ifm_count == 0) { 1906 warnx("%s: no media types?", name); 1907 goto proto_status; 1908 } 1909 1910 media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); 1911 if (media_list == NULL) 1912 err(1, "malloc"); 1913 ifmr.ifm_ulist = media_list; 1914 1915 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) 1916 err(1, "SIOCGIFMEDIA"); 1917 1918 printf("\tmedia: "); 1919 print_media_word(ifmr.ifm_current, 1, 0); 1920 if (ifmr.ifm_active != ifmr.ifm_current) { 1921 putchar(' '); 1922 putchar('('); 1923 print_media_word(ifmr.ifm_active, 0, 0); 1924 putchar(')'); 1925 } 1926 putchar('\n'); 1927 1928 if (ifmr.ifm_status & IFM_STATUS_VALID) { 1929 const struct ifmedia_status_description *ifms; 1930 int bitno, found = 0; 1931 1932 printf("\tstatus: "); 1933 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { 1934 for (ifms = ifm_status_descriptions; 1935 ifms->ifms_valid != 0; ifms++) { 1936 if (ifms->ifms_type != 1937 IFM_TYPE(ifmr.ifm_current) || 1938 ifms->ifms_valid != 1939 ifm_status_valid_list[bitno]) 1940 continue; 1941 printf("%s%s", found ? ", " : "", 1942 IFM_STATUS_DESC(ifms, ifmr.ifm_status)); 1943 found = 1; 1944 1945 /* 1946 * For each valid indicator bit, there's 1947 * only one entry for each media type, so 1948 * terminate the inner loop now. 1949 */ 1950 break; 1951 } 1952 } 1953 1954 if (found == 0) 1955 printf("unknown"); 1956 putchar('\n'); 1957 } 1958 1959 if (mflag) { 1960 int type, printed_type; 1961 1962 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) { 1963 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { 1964 if (IFM_TYPE(media_list[i]) == type) { 1965 if (printed_type == 0) { 1966 printf("\tsupported %s media:\n", 1967 get_media_type_string(type)); 1968 printed_type = 1; 1969 } 1970 printf("\t\t"); 1971 print_media_word(media_list[i], 0, 1); 1972 printf("\n"); 1973 } 1974 } 1975 } 1976 } 1977 1978 free(media_list); 1979 1980 proto_status: 1981 if ((p = afp) != NULL) { 1982 (*p->af_status)(1); 1983 } else for (p = afs; p->af_name; p++) { 1984 ifr.ifr_addr.sa_family = p->af_af; 1985 (*p->af_status)(0); 1986 } 1987} 1988 1989void 1990tunnel_status() 1991{ 1992 char psrcaddr[NI_MAXHOST]; 1993 char pdstaddr[NI_MAXHOST]; 1994 const char *ver = ""; 1995#ifdef NI_WITHSCOPEID 1996 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 1997#else 1998 const int niflag = NI_NUMERICHOST; 1999#endif 2000 struct if_laddrreq req; 2001 2002 psrcaddr[0] = pdstaddr[0] = '\0'; 2003 2004 memset(&req, 0, sizeof(req)); 2005 strncpy(req.iflr_name, name, IFNAMSIZ); 2006 if (ioctl(s, SIOCGLIFPHYADDR, (caddr_t)&req) < 0) 2007 return; 2008#ifdef INET6 2009 if (req.addr.ss_family == AF_INET6) 2010 in6_fillscopeid((struct sockaddr_in6 *)&req.addr); 2011#endif 2012 getnameinfo((struct sockaddr *)&req.addr, req.addr.ss_len, 2013 psrcaddr, sizeof(psrcaddr), 0, 0, niflag); 2014#ifdef INET6 2015 if (req.addr.ss_family == AF_INET6) 2016 ver = "6"; 2017#endif 2018 2019#ifdef INET6 2020 if (req.dstaddr.ss_family == AF_INET6) 2021 in6_fillscopeid((struct sockaddr_in6 *)&req.dstaddr); 2022#endif 2023 getnameinfo((struct sockaddr *)&req.dstaddr, req.dstaddr.ss_len, 2024 pdstaddr, sizeof(pdstaddr), 0, 0, niflag); 2025 2026 printf("\ttunnel inet%s %s --> %s\n", ver, psrcaddr, pdstaddr); 2027} 2028 2029void 2030vlan_status() 2031{ 2032 struct vlanreq vlr; 2033 2034 if (strncmp(ifr.ifr_name, "vlan", 4) != 0 || 2035 !isdigit(ifr.ifr_name[4])) 2036 return; 2037 2038 memset(&vlr, 0, sizeof(vlr)); 2039 ifr.ifr_data = (caddr_t)&vlr; 2040 2041 if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) 2042 return; 2043 2044 if (vlr.vlr_tag || vlr.vlr_parent[0] != '\0') 2045 printf("\tvlan: %d parent: %s\n", 2046 vlr.vlr_tag, vlr.vlr_parent[0] == '\0' ? 2047 "<none>" : vlr.vlr_parent); 2048} 2049 2050void 2051in_alias(creq) 2052 struct ifreq *creq; 2053{ 2054 struct sockaddr_in *sin; 2055 int alias; 2056 2057 if (lflag) 2058 return; 2059 2060 alias = 1; 2061 2062 /* Get the non-alias address for this interface. */ 2063 getsock(AF_INET); 2064 if (s < 0) { 2065 if (errno == EPROTONOSUPPORT) 2066 return; 2067 err(1, "socket"); 2068 } 2069 (void) memset(&ifr, 0, sizeof(ifr)); 2070 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2071 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 2072 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2073 return; 2074 } else 2075 warn("SIOCGIFADDR"); 2076 } 2077 /* If creq and ifr are the same address, this is not an alias. */ 2078 if (memcmp(&ifr.ifr_addr, &creq->ifr_addr, 2079 sizeof(creq->ifr_addr)) == 0) 2080 alias = 0; 2081 (void) memset(&addreq, 0, sizeof(addreq)); 2082 (void) strncpy(addreq.ifra_name, name, sizeof(addreq.ifra_name)); 2083 addreq.ifra_addr = creq->ifr_addr; 2084 if (ioctl(s, SIOCGIFALIAS, (caddr_t)&addreq) < 0) { 2085 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2086 return; 2087 } else 2088 warn("SIOCGIFALIAS"); 2089 } 2090 2091 sin = (struct sockaddr_in *)&addreq.ifra_addr; 2092 printf("\tinet %s%s", alias ? "alias " : "", inet_ntoa(sin->sin_addr)); 2093 2094 if (flags & IFF_POINTOPOINT) { 2095 sin = (struct sockaddr_in *)&addreq.ifra_dstaddr; 2096 printf(" -> %s", inet_ntoa(sin->sin_addr)); 2097 } 2098 2099 sin = (struct sockaddr_in *)&addreq.ifra_mask; 2100 printf(" netmask 0x%x", ntohl(sin->sin_addr.s_addr)); 2101 2102 if (flags & IFF_BROADCAST) { 2103 sin = (struct sockaddr_in *)&addreq.ifra_broadaddr; 2104 printf(" broadcast %s", inet_ntoa(sin->sin_addr)); 2105 } 2106 printf("\n"); 2107} 2108 2109void 2110in_status(force) 2111 int force; 2112{ 2113 struct ifaddrs *ifap, *ifa; 2114 struct ifreq ifr; 2115 2116 if (getifaddrs(&ifap) != 0) 2117 err(1, "getifaddrs"); 2118 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2119 if (strcmp(name, ifa->ifa_name) != 0) 2120 continue; 2121 if (ifa->ifa_addr->sa_family != AF_INET) 2122 continue; 2123 if (sizeof(ifr.ifr_addr) < ifa->ifa_addr->sa_len) 2124 continue; 2125 2126 memset(&ifr, 0, sizeof(ifr)); 2127 strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); 2128 memcpy(&ifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 2129 in_alias(&ifr); 2130 } 2131 freeifaddrs(ifap); 2132} 2133 2134void 2135setifprefixlen(addr, d) 2136 const char *addr; 2137 int d; 2138{ 2139 if (*afp->af_getprefix) 2140 (*afp->af_getprefix)(addr, MASK); 2141 explicit_prefix = 1; 2142} 2143 2144#ifdef INET6 2145void 2146in6_fillscopeid(sin6) 2147 struct sockaddr_in6 *sin6; 2148{ 2149#if defined(__KAME__) && defined(KAME_SCOPEID) 2150 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 2151 sin6->sin6_scope_id = 2152 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 2153 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 2154 } 2155#endif 2156} 2157 2158/* XXX not really an alias */ 2159void 2160in6_alias(creq) 2161 struct in6_ifreq *creq; 2162{ 2163 struct sockaddr_in6 *sin6; 2164 char hbuf[NI_MAXHOST]; 2165 u_int32_t scopeid; 2166#ifdef NI_WITHSCOPEID 2167 const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID; 2168#else 2169 const int niflag = NI_NUMERICHOST; 2170#endif 2171 2172 /* Get the non-alias address for this interface. */ 2173 getsock(AF_INET6); 2174 if (s < 0) { 2175 if (errno == EPROTONOSUPPORT) 2176 return; 2177 err(1, "socket"); 2178 } 2179 2180 sin6 = (struct sockaddr_in6 *)&creq->ifr_addr; 2181 2182 in6_fillscopeid(sin6); 2183 scopeid = sin6->sin6_scope_id; 2184 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 2185 hbuf, sizeof(hbuf), NULL, 0, niflag)) 2186 strncpy(hbuf, "", sizeof(hbuf)); /* some message? */ 2187 printf("\tinet6 %s", hbuf); 2188 2189 if (flags & IFF_POINTOPOINT) { 2190 (void) memset(&ifr6, 0, sizeof(ifr6)); 2191 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2192 ifr6.ifr_addr = creq->ifr_addr; 2193 if (ioctl(s, SIOCGIFDSTADDR_IN6, (caddr_t)&ifr6) < 0) { 2194 if (errno != EADDRNOTAVAIL) 2195 warn("SIOCGIFDSTADDR_IN6"); 2196 (void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr)); 2197 ifr6.ifr_addr.sin6_family = AF_INET6; 2198 ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6); 2199 } 2200 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 2201 in6_fillscopeid(sin6); 2202 hbuf[0] = '\0'; 2203 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 2204 hbuf, sizeof(hbuf), NULL, 0, niflag)) 2205 strncpy(hbuf, "", sizeof(hbuf)); /* some message? */ 2206 printf(" -> %s", hbuf); 2207 } 2208 2209 (void) memset(&ifr6, 0, sizeof(ifr6)); 2210 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2211 ifr6.ifr_addr = creq->ifr_addr; 2212 if (ioctl(s, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) { 2213 if (errno != EADDRNOTAVAIL) 2214 warn("SIOCGIFNETMASK_IN6"); 2215 } else { 2216 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 2217 printf(" prefixlen %d", prefix(&sin6->sin6_addr, 2218 sizeof(struct in6_addr))); 2219 } 2220 2221 (void) memset(&ifr6, 0, sizeof(ifr6)); 2222 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2223 ifr6.ifr_addr = creq->ifr_addr; 2224 if (ioctl(s, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) < 0) { 2225 if (errno != EADDRNOTAVAIL) 2226 warn("SIOCGIFAFLAG_IN6"); 2227 } else { 2228 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST) 2229 printf(" anycast"); 2230 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) 2231 printf(" tentative"); 2232 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) 2233 printf(" duplicated"); 2234 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED) 2235 printf(" detached"); 2236 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) 2237 printf(" deprecated"); 2238 } 2239 2240 if (scopeid) 2241 printf(" scopeid 0x%x", scopeid); 2242 2243 if (Lflag) { 2244 struct in6_addrlifetime *lifetime; 2245 (void) memset(&ifr6, 0, sizeof(ifr6)); 2246 (void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name)); 2247 ifr6.ifr_addr = creq->ifr_addr; 2248 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 2249 if (ioctl(s, SIOCGIFALIFETIME_IN6, (caddr_t)&ifr6) < 0) { 2250 if (errno != EADDRNOTAVAIL) 2251 warn("SIOCGIFALIFETIME_IN6"); 2252 } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { 2253 time_t t = time(NULL); 2254 printf(" pltime "); 2255 if (lifetime->ia6t_preferred) { 2256 printf("%s", lifetime->ia6t_preferred < t 2257 ? "0" 2258 : sec2str(lifetime->ia6t_preferred - t)); 2259 } else 2260 printf("infty"); 2261 2262 printf(" vltime "); 2263 if (lifetime->ia6t_expire) { 2264 printf("%s", lifetime->ia6t_expire < t 2265 ? "0" 2266 : sec2str(lifetime->ia6t_expire - t)); 2267 } else 2268 printf("infty"); 2269 } 2270 } 2271 2272 printf("\n"); 2273} 2274 2275void 2276in6_status(force) 2277 int force; 2278{ 2279 struct ifaddrs *ifap, *ifa; 2280 struct in6_ifreq ifr; 2281 2282 if (getifaddrs(&ifap) != 0) 2283 err(1, "getifaddrs"); 2284 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 2285 if (strcmp(name, ifa->ifa_name) != 0) 2286 continue; 2287 if (ifa->ifa_addr->sa_family != AF_INET6) 2288 continue; 2289 if (sizeof(ifr.ifr_addr) < ifa->ifa_addr->sa_len) 2290 continue; 2291 2292 memset(&ifr, 0, sizeof(ifr)); 2293 strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); 2294 memcpy(&ifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len); 2295 in6_alias(&ifr); 2296 } 2297 freeifaddrs(ifap); 2298} 2299#endif /*INET6*/ 2300 2301#ifndef INET_ONLY 2302 2303void 2304at_status(force) 2305 int force; 2306{ 2307 struct sockaddr_at *sat, null_sat; 2308 struct netrange *nr; 2309 2310 getsock(AF_APPLETALK); 2311 if (s < 0) { 2312 if (errno == EPROTONOSUPPORT) 2313 return; 2314 err(1, "socket"); 2315 } 2316 (void) memset(&ifr, 0, sizeof(ifr)); 2317 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2318 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 2319 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2320 if (!force) 2321 return; 2322 (void) memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 2323 } else 2324 warn("SIOCGIFADDR"); 2325 } 2326 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 2327 sat = (struct sockaddr_at *)&ifr.ifr_addr; 2328 2329 (void) memset(&null_sat, 0, sizeof(null_sat)); 2330 2331 nr = (struct netrange *) &sat->sat_zero; 2332 printf("\tatalk %d.%d range %d-%d phase %d", 2333 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 2334 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase); 2335 if (flags & IFF_POINTOPOINT) { 2336 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 2337 if (errno == EADDRNOTAVAIL) 2338 (void) memset(&ifr.ifr_addr, 0, 2339 sizeof(ifr.ifr_addr)); 2340 else 2341 warn("SIOCGIFDSTADDR"); 2342 } 2343 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 2344 sat = (struct sockaddr_at *)&ifr.ifr_dstaddr; 2345 if (!sat) 2346 sat = &null_sat; 2347 printf("--> %d.%d", 2348 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 2349 } 2350 if (flags & IFF_BROADCAST) { 2351 /* note RTAX_BRD overlap with IFF_POINTOPOINT */ 2352 sat = (struct sockaddr_at *)&ifr.ifr_broadaddr; 2353 if (sat) 2354 printf(" broadcast %d.%d", ntohs(sat->sat_addr.s_net), 2355 sat->sat_addr.s_node); 2356 } 2357 putchar('\n'); 2358} 2359 2360void 2361xns_status(force) 2362 int force; 2363{ 2364 struct sockaddr_ns *sns; 2365 2366 getsock(AF_NS); 2367 if (s < 0) { 2368 if (errno == EPROTONOSUPPORT) 2369 return; 2370 err(1, "socket"); 2371 } 2372 (void) memset(&ifr, 0, sizeof(ifr)); 2373 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2374 if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) { 2375 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2376 if (!force) 2377 return; 2378 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 2379 } else 2380 warn("SIOCGIFADDR"); 2381 } 2382 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 2383 sns = (struct sockaddr_ns *)&ifr.ifr_addr; 2384 printf("\tns %s ", ns_ntoa(sns->sns_addr)); 2385 if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */ 2386 if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) { 2387 if (errno == EADDRNOTAVAIL) 2388 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 2389 else 2390 warn("SIOCGIFDSTADDR"); 2391 } 2392 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 2393 sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr; 2394 printf("--> %s ", ns_ntoa(sns->sns_addr)); 2395 } 2396 putchar('\n'); 2397} 2398 2399void 2400iso_status(force) 2401 int force; 2402{ 2403 struct sockaddr_iso *siso; 2404 struct iso_ifreq ifr; 2405 2406 getsock(AF_ISO); 2407 if (s < 0) { 2408 if (errno == EPROTONOSUPPORT) 2409 return; 2410 err(1, "socket"); 2411 } 2412 (void) memset(&ifr, 0, sizeof(ifr)); 2413 (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2414 if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) { 2415 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 2416 if (!force) 2417 return; 2418 (void) memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr)); 2419 } else 2420 warn("SIOCGIFADDR_ISO"); 2421 } 2422 (void) strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); 2423 siso = &ifr.ifr_Addr; 2424 printf("\tiso %s ", iso_ntoa(&siso->siso_addr)); 2425 if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) { 2426 if (errno == EADDRNOTAVAIL) 2427 memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr)); 2428 else 2429 warn("SIOCGIFNETMASK_ISO"); 2430 } else { 2431 if (siso->siso_len > offsetof(struct sockaddr_iso, siso_addr)) 2432 siso->siso_addr.isoa_len = siso->siso_len 2433 - offsetof(struct sockaddr_iso, siso_addr); 2434 printf("\n\t\tnetmask %s ", iso_ntoa(&siso->siso_addr)); 2435 } 2436 if (flags & IFF_POINTOPOINT) { 2437 if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) { 2438 if (errno == EADDRNOTAVAIL) 2439 memset(&ifr.ifr_Addr, 0, sizeof(ifr.ifr_Addr)); 2440 else 2441 warn("SIOCGIFDSTADDR_ISO"); 2442 } 2443 (void) strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); 2444 siso = &ifr.ifr_Addr; 2445 printf("--> %s ", iso_ntoa(&siso->siso_addr)); 2446 } 2447 putchar('\n'); 2448} 2449 2450#endif /* INET_ONLY */ 2451 2452#define SIN(x) ((struct sockaddr_in *) &(x)) 2453struct sockaddr_in *sintab[] = { 2454SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), 2455SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; 2456 2457void 2458in_getaddr(s, which) 2459 const char *s; 2460 int which; 2461{ 2462 struct sockaddr_in *sin = sintab[which]; 2463 struct hostent *hp; 2464 struct netent *np; 2465 2466 sin->sin_len = sizeof(*sin); 2467 if (which != MASK) 2468 sin->sin_family = AF_INET; 2469 2470 if (which == ADDR) { 2471 char *p = NULL; 2472 if ((p = strrchr(s, '/')) != NULL) { 2473 *p = '\0'; 2474 in_getprefix(p + 1, MASK); 2475 } 2476 } 2477 2478 if (inet_aton(s, &sin->sin_addr) == 0) { 2479 if ((hp = gethostbyname(s)) != NULL) 2480 (void) memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); 2481 else if ((np = getnetbyname(s)) != NULL) 2482 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 2483 else 2484 errx(1, "%s: bad value", s); 2485 } 2486} 2487 2488void 2489in_getprefix(plen, which) 2490 const char *plen; 2491 int which; 2492{ 2493 register struct sockaddr_in *sin = sintab[which]; 2494 register u_char *cp; 2495 int len = strtol(plen, (char **)NULL, 10); 2496 2497 if ((len < 0) || (len > 32)) 2498 errx(1, "%s: bad value", plen); 2499 sin->sin_len = sizeof(*sin); 2500 if (which != MASK) 2501 sin->sin_family = AF_INET; 2502 if ((len == 0) || (len == 32)) { 2503 memset(&sin->sin_addr, 0xff, sizeof(struct in_addr)); 2504 return; 2505 } 2506 memset((void *)&sin->sin_addr, 0x00, sizeof(sin->sin_addr)); 2507 for (cp = (u_char *)&sin->sin_addr; len > 7; len -= 8) 2508 *cp++ = 0xff; 2509 if (len) 2510 *cp = 0xff << (8 - len); 2511} 2512 2513/* 2514 * Print a value a la the %b format of the kernel's printf 2515 */ 2516void 2517printb(s, v, bits) 2518 const char *s; 2519 unsigned short v; 2520 const char *bits; 2521{ 2522 int i, any = 0; 2523 char c; 2524 2525 if (bits && *bits == 8) 2526 printf("%s=%o", s, v); 2527 else 2528 printf("%s=%x", s, v); 2529 bits++; 2530 if (bits) { 2531 putchar('<'); 2532 while ((i = *bits++) != 0) { 2533 if (v & (1 << (i-1))) { 2534 if (any) 2535 putchar(','); 2536 any = 1; 2537 for (; (c = *bits) > 32; bits++) 2538 putchar(c); 2539 } else 2540 for (; *bits > 32; bits++) 2541 ; 2542 } 2543 putchar('>'); 2544 } 2545} 2546 2547#ifdef INET6 2548#define SIN6(x) ((struct sockaddr_in6 *) &(x)) 2549struct sockaddr_in6 *sin6tab[] = { 2550SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 2551SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 2552 2553void 2554in6_getaddr(s, which) 2555 const char *s; 2556 int which; 2557{ 2558#if defined(__KAME__) && defined(KAME_SCOPEID) 2559 struct sockaddr_in6 *sin6 = sin6tab[which]; 2560 struct addrinfo hints, *res; 2561 int error; 2562 2563 memset(&hints, 0, sizeof(hints)); 2564 hints.ai_family = AF_INET6; 2565 hints.ai_socktype = SOCK_DGRAM; 2566#if 0 /* in_getaddr() allows FQDN */ 2567 hints.ai_flags = AI_NUMERICHOST; 2568#endif 2569 error = getaddrinfo(s, "0", &hints, &res); 2570 if (error) 2571 errx(1, "%s: %s", s, gai_strerror(error)); 2572 if (res->ai_next) 2573 errx(1, "%s: resolved to multiple hosts", s); 2574 if (res->ai_addrlen != sizeof(struct sockaddr_in6)) 2575 errx(1, "%s: bad value", s); 2576 memcpy(sin6, res->ai_addr, res->ai_addrlen); 2577 freeaddrinfo(res); 2578 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && sin6->sin6_scope_id) { 2579 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] = 2580 htons(sin6->sin6_scope_id); 2581 sin6->sin6_scope_id = 0; 2582 } 2583#else 2584 struct sockaddr_in6 *sin = sin6tab[which]; 2585 2586 sin->sin6_len = sizeof(*sin); 2587 if (which != MASK) 2588 sin->sin6_family = AF_INET6; 2589 2590 if (which == ADDR) { 2591 char *p = NULL; 2592 if((p = strrchr(s, '/')) != NULL) { 2593 *p = '\0'; 2594 in6_getprefix(p + 1, MASK); 2595 explicit_prefix = 1; 2596 } 2597 } 2598 2599 if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1) 2600 errx(1, "%s: bad value", s); 2601#endif 2602} 2603 2604void 2605in6_getprefix(plen, which) 2606 const char *plen; 2607 int which; 2608{ 2609 register struct sockaddr_in6 *sin = sin6tab[which]; 2610 register u_char *cp; 2611 int len = strtol(plen, (char **)NULL, 10); 2612 2613 if ((len < 0) || (len > 128)) 2614 errx(1, "%s: bad value", plen); 2615 sin->sin6_len = sizeof(*sin); 2616 if (which != MASK) 2617 sin->sin6_family = AF_INET6; 2618 if ((len == 0) || (len == 128)) { 2619 memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr)); 2620 return; 2621 } 2622 memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr)); 2623 for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8) 2624 *cp++ = 0xff; 2625 if (len) 2626 *cp = 0xff << (8 - len); 2627} 2628 2629int 2630prefix(val, size) 2631 void *val; 2632 int size; 2633{ 2634 register u_char *name = (u_char *)val; 2635 register int byte, bit, plen = 0; 2636 2637 for (byte = 0; byte < size; byte++, plen += 8) 2638 if (name[byte] != 0xff) 2639 break; 2640 if (byte == size) 2641 return (plen); 2642 for (bit = 7; bit != 0; bit--, plen++) 2643 if (!(name[byte] & (1 << bit))) 2644 break; 2645 for (; bit != 0; bit--) 2646 if (name[byte] & (1 << bit)) 2647 return(0); 2648 byte++; 2649 for (; byte < size; byte++) 2650 if (name[byte]) 2651 return(0); 2652 return (plen); 2653} 2654#endif /*INET6*/ 2655 2656#ifndef INET_ONLY 2657void 2658at_getaddr(addr, which) 2659 const char *addr; 2660 int which; 2661{ 2662 struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr; 2663 u_int net, node; 2664 2665 sat->sat_family = AF_APPLETALK; 2666 sat->sat_len = sizeof(*sat); 2667 if (which == MASK) 2668 errx(1, "AppleTalk does not use netmasks\n"); 2669 if (sscanf(addr, "%u.%u", &net, &node) != 2 2670 || net == 0 || net > 0xffff || node == 0 || node > 0xfe) 2671 errx(1, "%s: illegal address", addr); 2672 sat->sat_addr.s_net = htons(net); 2673 sat->sat_addr.s_node = node; 2674} 2675 2676void 2677setatrange(range, d) 2678 const char *range; 2679 int d; 2680{ 2681 u_short first = 123, last = 123; 2682 2683 if (sscanf(range, "%hu-%hu", &first, &last) != 2 2684 || first == 0 || first > 0xffff 2685 || last == 0 || last > 0xffff || first > last) 2686 errx(1, "%s: illegal net range: %u-%u", range, first, last); 2687 at_nr.nr_firstnet = htons(first); 2688 at_nr.nr_lastnet = htons(last); 2689} 2690 2691void 2692setatphase(phase, d) 2693 const char *phase; 2694 int d; 2695{ 2696 if (!strcmp(phase, "1")) 2697 at_nr.nr_phase = 1; 2698 else if (!strcmp(phase, "2")) 2699 at_nr.nr_phase = 2; 2700 else 2701 errx(1, "%s: illegal phase", phase); 2702} 2703 2704void 2705checkatrange(sat) 2706 struct sockaddr_at *sat; 2707{ 2708 if (at_nr.nr_phase == 0) 2709 at_nr.nr_phase = 2; /* Default phase 2 */ 2710 if (at_nr.nr_firstnet == 0) 2711 at_nr.nr_firstnet = /* Default range of one */ 2712 at_nr.nr_lastnet = sat->sat_addr.s_net; 2713 printf("\tatalk %d.%d range %d-%d phase %d\n", 2714 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 2715 ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase); 2716 if ((u_short) ntohs(at_nr.nr_firstnet) > 2717 (u_short) ntohs(sat->sat_addr.s_net) 2718 || (u_short) ntohs(at_nr.nr_lastnet) < 2719 (u_short) ntohs(sat->sat_addr.s_net)) 2720 errx(1, "AppleTalk address is not in range"); 2721 *((struct netrange *) &sat->sat_zero) = at_nr; 2722} 2723 2724#define SNS(x) ((struct sockaddr_ns *) &(x)) 2725struct sockaddr_ns *snstab[] = { 2726SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr), 2727SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)}; 2728 2729void 2730xns_getaddr(addr, which) 2731 const char *addr; 2732 int which; 2733{ 2734 struct sockaddr_ns *sns = snstab[which]; 2735 2736 sns->sns_family = AF_NS; 2737 sns->sns_len = sizeof(*sns); 2738 sns->sns_addr = ns_addr(addr); 2739 if (which == MASK) 2740 puts("Attempt to set XNS netmask will be ineffectual"); 2741} 2742 2743#define SISO(x) ((struct sockaddr_iso *) &(x)) 2744struct sockaddr_iso *sisotab[] = { 2745SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr), 2746SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)}; 2747 2748void 2749iso_getaddr(addr, which) 2750 const char *addr; 2751 int which; 2752{ 2753 struct sockaddr_iso *siso = sisotab[which]; 2754 siso->siso_addr = *iso_addr(addr); 2755 2756 if (which == MASK) { 2757 siso->siso_len = TSEL(siso) - (caddr_t)(siso); 2758 siso->siso_nlen = 0; 2759 } else { 2760 siso->siso_len = sizeof(*siso); 2761 siso->siso_family = AF_ISO; 2762 } 2763} 2764 2765void 2766setsnpaoffset(val, d) 2767 const char *val; 2768 int d; 2769{ 2770 iso_addreq.ifra_snpaoffset = atoi(val); 2771} 2772 2773void 2774setnsellength(val, d) 2775 const char *val; 2776 int d; 2777{ 2778 nsellength = atoi(val); 2779 if (nsellength < 0) 2780 errx(1, "Negative NSEL length is absurd"); 2781 if (afp == 0 || afp->af_af != AF_ISO) 2782 errx(1, "Setting NSEL length valid only for iso"); 2783} 2784 2785void 2786fixnsel(s) 2787 struct sockaddr_iso *s; 2788{ 2789 if (s->siso_family == 0) 2790 return; 2791 s->siso_tlen = nsellength; 2792} 2793 2794void 2795adjust_nsellength() 2796{ 2797 fixnsel(sisotab[RIDADDR]); 2798 fixnsel(sisotab[ADDR]); 2799 fixnsel(sisotab[DSTADDR]); 2800} 2801 2802#endif /* INET_ONLY */ 2803 2804void 2805usage() 2806{ 2807 const char *progname = getprogname(); 2808 2809 fprintf(stderr, 2810 "usage: %s [ -m ] " 2811#ifdef INET6 2812 "[ -L ] " 2813#endif 2814 "interface\n" 2815 "\t[ af [ address [ dest_addr ] ] [ netmask mask ] [ prefixlen n ]\n" 2816 "\t\t[ alias | -alias ] ]\n" 2817 "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n" 2818 "\t[ nwid network_id ] [ nwkey network_key | -nwkey ]\n" 2819 "\t[ powersave | -powersave ] [ powersavesleep duration ]\n" 2820 "\t[ [ af ] tunnel src_addr dest_addr ] [ deletetunnel ]\n" 2821 "\t[ arp | -arp ]\n" 2822 "\t[ media type ] [ mediaopt opts ] [ -mediaopt opts ] " 2823 "[ instance minst ]\n" 2824 "\t[ vlan n vlanif i ]\n" 2825 "\t[ anycast | -anycast ] [ deprecated | -deprecated ]\n" 2826 "\t[ tentative | -tentative ] [ pltime n ] [ vltime n ]\n" 2827 "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n" 2828 " %s -a [ -m ] [ -d ] [ -u ] [ af ]\n" 2829 " %s -l [ -b ] [ -d ] [ -u ] [ -s ]\n" 2830 " %s -C\n" 2831 " %s interface create\n" 2832 " %s interface destroy\n", 2833 progname, progname, progname, progname, progname, progname); 2834 exit(1); 2835} 2836 2837#ifdef INET6 2838char * 2839sec2str(total) 2840 time_t total; 2841{ 2842 static char result[256]; 2843 int days, hours, mins, secs; 2844 int first = 1; 2845 char *p = result; 2846 char *end = &result[sizeof(result)]; 2847 int n; 2848 2849 if (0) { /*XXX*/ 2850 days = total / 3600 / 24; 2851 hours = (total / 3600) % 24; 2852 mins = (total / 60) % 60; 2853 secs = total % 60; 2854 2855 if (days) { 2856 first = 0; 2857 n = snprintf(p, end - p, "%dd", days); 2858 if (n < 0 || n >= end - p) 2859 return(result); 2860 p += n; 2861 } 2862 if (!first || hours) { 2863 first = 0; 2864 n = snprintf(p, end - p, "%dh", hours); 2865 if (n < 0 || n >= end - p) 2866 return(result); 2867 p += n; 2868 } 2869 if (!first || mins) { 2870 first = 0; 2871 n = snprintf(p, end - p, "%dm", mins); 2872 if (n < 0 || n >= end - p) 2873 return(result); 2874 p += n; 2875 } 2876 snprintf(p, end - p, "%ds", secs); 2877 } else 2878 snprintf(p, end - p, "%lu", (u_long)total); 2879 2880 return(result); 2881} 2882#endif 2883