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