1/* $OpenBSD: ifconfig.c,v 1.472 2024/05/18 02:44:22 jsg Exp $ */ 2/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */ 3 4/* 5 * Copyright (c) 1983, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33/*- 34 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. 35 * All rights reserved. 36 * 37 * This code is derived from software contributed to The NetBSD Foundation 38 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 39 * NASA Ames Research Center. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60 * POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63#include <sys/socket.h> 64#include <sys/ioctl.h> 65#include <sys/time.h> 66 67#include <net/if.h> 68#include <net/if_dl.h> 69#include <net/if_media.h> 70#include <net/if_types.h> 71#include <netinet/in.h> 72#include <netinet/in_var.h> 73#include <netinet6/in6_var.h> 74#include <netinet6/nd6.h> 75#include <arpa/inet.h> 76#include <netinet/ip_ipsp.h> 77#include <netinet/if_ether.h> 78#include <net80211/ieee80211.h> 79#include <net80211/ieee80211_ioctl.h> 80#include <net/pfvar.h> 81#include <net/if_pfsync.h> 82#include <net/if_pflow.h> 83#include <net/if_pppoe.h> 84#include <net/if_trunk.h> 85#include <net/if_wg.h> 86#include <net/trunklacp.h> 87#include <net/if_sppp.h> 88#include <net/ppp_defs.h> 89 90#include <netinet/ip_carp.h> 91 92#include <netdb.h> 93 94#include <net/if_vlan_var.h> 95 96#include <netmpls/mpls.h> 97 98#include <ctype.h> 99#include <err.h> 100#include <errno.h> 101#include <stdio.h> 102#include <stdint.h> 103#include <stdlib.h> 104#include <stddef.h> 105#include <string.h> 106#include <unistd.h> 107#include <limits.h> 108#include <resolv.h> 109#include <util.h> 110#include <ifaddrs.h> 111 112#ifndef SMALL 113#include <dev/usb/mbim.h> 114#include <dev/usb/if_umb.h> 115#endif /* SMALL */ 116 117#include "ifconfig.h" 118 119#ifndef nitems 120#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 121#endif 122 123#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 124#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 125 126#define HWFEATURESBITS \ 127 "\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" \ 128 "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6" \ 129 "\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL" 130 131struct ifencap { 132 unsigned int ife_flags; 133#define IFE_VNETID_MASK 0xf 134#define IFE_VNETID_NOPE 0x0 135#define IFE_VNETID_NONE 0x1 136#define IFE_VNETID_ANY 0x2 137#define IFE_VNETID_SET 0x3 138 int64_t ife_vnetid; 139#define IFE_VNETFLOWID 0x10 140 141#define IFE_PARENT_MASK 0xf00 142#define IFE_PARENT_NOPE 0x000 143#define IFE_PARENT_NONE 0x100 144#define IFE_PARENT_SET 0x200 145 char ife_parent[IFNAMSIZ]; 146 147#define IFE_TXHPRIO_SET 0x1000 148 int ife_txhprio; 149#define IFE_RXHPRIO_SET 0x2000 150 int ife_rxhprio; 151}; 152 153struct ifreq ifr, ridreq; 154struct in_aliasreq in_addreq; 155struct in6_ifreq ifr6; 156struct in6_ifreq in6_ridreq; 157struct in6_aliasreq in6_addreq; 158struct sockaddr_in netmask; 159 160#ifndef SMALL 161int rdomainid; 162#endif /* SMALL */ 163 164char ifname[IFNAMSIZ]; 165int flags, xflags, setaddr, setipdst, doalias; 166u_long metric, mtu; 167int llprio; 168int clearaddr, sock; 169int newaddr = 0; 170int af = AF_INET; 171int explicit_prefix = 0; 172int Lflag = 1; 173int show_join = 0; 174 175int showmediaflag; 176int showcapsflag; 177int shownet80211chans; 178int shownet80211nodes; 179int showclasses; 180int showtransceiver; 181 182struct ifencap; 183 184struct ieee80211_join join; 185 186const char *lacpmodeactive = "active"; 187const char *lacpmodepassive = "passive"; 188const char *lacptimeoutfast = "fast"; 189const char *lacptimeoutslow = "slow"; 190 191void notealias(const char *, int); 192void setifaddr(const char *, int); 193void setiflladdr(const char *, int); 194void setifdstaddr(const char *, int); 195void setifflags(const char *, int); 196void setifxflags(const char *, int); 197void addaf(const char *, int); 198void removeaf(const char *, int); 199void setifbroadaddr(const char *, int); 200void setifmtu(const char *, int); 201void setifllprio(const char *, int); 202void setifnwid(const char *, int); 203void setifjoin(const char *, int); 204void delifjoin(const char *, int); 205void delifjoinlist(const char *, int); 206void showjoin(const char *, int); 207void setifbssid(const char *, int); 208void setifnwkey(const char *, int); 209void setifwpa(const char *, int); 210void setifwpaprotos(const char *, int); 211void setifwpaakms(const char *, int); 212void setifwpaciphers(const char *, int); 213void setifwpagroupcipher(const char *, int); 214void setifwpakey(const char *, int); 215void setifchan(const char *, int); 216void setifscan(const char *, int); 217void setifnwflag(const char *, int); 218void unsetifnwflag(const char *, int); 219void setifnetmask(const char *, int); 220void setifprefixlen(const char *, int); 221void setvnetid(const char *, int); 222void delvnetid(const char *, int); 223void getvnetid(struct ifencap *); 224void setifparent(const char *, int); 225void delifparent(const char *, int); 226void getifparent(struct ifencap *); 227void getencap(void); 228void setia6flags(const char *, int); 229void setia6pltime(const char *, int); 230void setia6vltime(const char *, int); 231void setia6lifetime(const char *, const char *); 232void setia6eui64(const char *, int); 233void setmedia(const char *, int); 234void setmediaopt(const char *, int); 235void setmediamode(const char *, int); 236void unsetmediamode(const char *, int); 237void clone_create(const char *, int); 238void clone_destroy(const char *, int); 239void unsetmediaopt(const char *, int); 240void setmediainst(const char *, int); 241int prefix(void *val, int); 242void getifgroups(void); 243void setifgroup(const char *, int); 244void unsetifgroup(const char *, int); 245void setgroupattribs(char *, int, char *[]); 246int printgroup(char *, int); 247void setautoconf(const char *, int); 248void settemporary(const char *, int); 249void settrunkport(const char *, int); 250void unsettrunkport(const char *, int); 251void settrunkproto(const char *, int); 252void settrunklacpmode(const char *, int); 253void settrunklacptimeout(const char *, int); 254void trunk_status(void); 255void list_cloners(void); 256 257#ifndef SMALL 258void setifrtlabel(const char *, int); 259void setrdomain(const char *, int); 260void unsetrdomain(const char *, int); 261void setkeepalive(const char *, const char *); 262void unsetkeepalive(const char *, int); 263void carp_status(void); 264void setcarp_advbase(const char *,int); 265void setcarp_advskew(const char *, int); 266void setcarppeer(const char *, int); 267void unsetcarppeer(const char *, int); 268void setcarp_passwd(const char *, int); 269void setcarp_vhid(const char *, int); 270void setcarp_state(const char *, int); 271void setcarpdev(const char *, int); 272void setcarp_nodes(const char *, int); 273void setcarp_balancing(const char *, int); 274void setpfsync_syncdev(const char *, int); 275void setpfsync_maxupd(const char *, int); 276void unsetpfsync_syncdev(const char *, int); 277void setpfsync_syncpeer(const char *, int); 278void unsetpfsync_syncpeer(const char *, int); 279void setpfsync_defer(const char *, int); 280void pfsync_status(void); 281void setvnetflowid(const char *, int); 282void delvnetflowid(const char *, int); 283void getvnetflowid(struct ifencap *); 284void gettxprio(struct ifencap *); 285void settxprio(const char *, int); 286void getrxprio(struct ifencap *); 287void setrxprio(const char *, int); 288void setmplslabel(const char *, int); 289void unsetmplslabel(const char *, int); 290void setpwe3cw(const char *, int); 291void unsetpwe3cw(const char *, int); 292void setpwe3fat(const char *, int); 293void unsetpwe3fat(const char *, int); 294void setpwe3neighbor(const char *, const char *); 295void unsetpwe3neighbor(const char *, int); 296void mpls_status(void); 297void settunnel(const char *, const char *); 298void settunneladdr(const char *, int); 299void deletetunnel(const char *, int); 300void settunnelinst(const char *, int); 301void unsettunnelinst(const char *, int); 302void settunnelttl(const char *, int); 303void settunneldf(const char *, int); 304void settunnelnodf(const char *, int); 305void settunnelecn(const char *, int); 306void settunnelnoecn(const char *, int); 307void setpppoe_dev(const char *,int); 308void setpppoe_svc(const char *,int); 309void setpppoe_ac(const char *,int); 310void pppoe_status(void); 311void setspppproto(const char *, int); 312void setspppname(const char *, int); 313void setspppkey(const char *, int); 314void setsppppeerproto(const char *, int); 315void setsppppeername(const char *, int); 316void setsppppeerkey(const char *, int); 317void setsppppeerflag(const char *, int); 318void unsetsppppeerflag(const char *, int); 319void sppp_status(void); 320void sppp_printproto(const char *, struct sauthreq *); 321void setifpriority(const char *, int); 322void setifpowersave(const char *, int); 323void setifmetric(const char *, int); 324void pflow_status(void); 325void pflow_addr(const char*, struct sockaddr_storage *); 326void setpflow_sender(const char *, int); 327void unsetpflow_sender(const char *, int); 328void setpflow_receiver(const char *, int); 329void unsetpflow_receiver(const char *, int); 330void setpflowproto(const char *, int); 331void setifipdst(const char *, int); 332void setifdesc(const char *, int); 333void unsetifdesc(const char *, int); 334void printifhwfeatures(const char *, int); 335void setpair(const char *, int); 336void unsetpair(const char *, int); 337void umb_status(void); 338void umb_printclasses(char *, int); 339int umb_parse_classes(const char *); 340void umb_setpin(const char *, int); 341void umb_chgpin(const char *, const char *); 342void umb_puk(const char *, const char *); 343void umb_pinop(int, int, const char *, const char *); 344void umb_apn(const char *, int); 345void umb_setclass(const char *, int); 346void umb_roaming(const char *, int); 347void utf16_to_char(uint16_t *, int, char *, size_t); 348int char_to_utf16(const char *, uint16_t *, size_t); 349void transceiver(const char *, int); 350void transceiverdump(const char *, int); 351 352/* WG */ 353void setwgpeer(const char *, int); 354void setwgpeerdesc(const char *, int); 355void setwgpeerep(const char *, const char *); 356void setwgpeeraip(const char *, int); 357void setwgpeerpsk(const char *, int); 358void setwgpeerpka(const char *, int); 359void setwgport(const char *, int); 360void setwgkey(const char *, int); 361void setwgrtable(const char *, int); 362 363void unsetwgpeer(const char *, int); 364void unsetwgpeerdesc(const char *, int); 365void unsetwgpeerpsk(const char *, int); 366void unsetwgpeerall(const char *, int); 367 368void wg_status(int); 369#else 370void setignore(const char *, int); 371#endif 372 373struct if_clonereq *get_cloners(void); 374int findmac(const char *); 375 376/* 377 * Media stuff. Whenever a media command is first performed, the 378 * currently select media is grabbed for this interface. If `media' 379 * is given, the current media word is modified. `mediaopt' commands 380 * only modify the set and clear words. They then operate on the 381 * current media word later. 382 */ 383uint64_t media_current; 384uint64_t mediaopt_set; 385uint64_t mediaopt_clear; 386 387int actions; /* Actions performed */ 388 389#define A_MEDIA 0x0001 /* media command */ 390#define A_MEDIAOPTSET 0x0002 /* mediaopt command */ 391#define A_MEDIAOPTCLR 0x0004 /* -mediaopt command */ 392#define A_MEDIAOPT (A_MEDIAOPTSET|A_MEDIAOPTCLR) 393#define A_MEDIAINST 0x0008 /* instance or inst command */ 394#define A_MEDIAMODE 0x0010 /* mode command */ 395#define A_JOIN 0x0020 /* join */ 396#define A_WIREGUARD 0x0040 /* any WireGuard command */ 397#define A_SILENT 0x8000000 /* doing operation, do not print */ 398 399#define NEXTARG0 0xffffff 400#define NEXTARG 0xfffffe 401#define NEXTARG2 0xfffffd 402 403const struct cmd { 404 char *c_name; 405 int c_parameter; /* NEXTARG means next argv */ 406 int c_action; /* defered action */ 407 void (*c_func)(const char *, int); 408 void (*c_func2)(const char *, const char *); 409} cmds[] = { 410 { "up", IFF_UP, 0, setifflags } , 411 { "down", -IFF_UP, 0, setifflags }, 412 { "arp", -IFF_NOARP, 0, setifflags }, 413 { "-arp", IFF_NOARP, 0, setifflags }, 414 { "debug", IFF_DEBUG, 0, setifflags }, 415 { "-debug", -IFF_DEBUG, 0, setifflags }, 416 { "alias", IFF_UP, 0, notealias }, 417 { "-alias", -IFF_UP, 0, notealias }, 418 { "delete", -IFF_UP, 0, notealias }, 419 { "netmask", NEXTARG, 0, setifnetmask }, 420 { "mtu", NEXTARG, 0, setifmtu }, 421 { "nwid", NEXTARG, 0, setifnwid }, 422 { "-nwid", -1, 0, setifnwid }, 423 { "join", NEXTARG, 0, setifjoin }, 424 { "-join", NEXTARG, 0, delifjoin }, 425 { "joinlist", NEXTARG0, 0, showjoin }, 426 { "-joinlist", -1, 0, delifjoinlist }, 427 { "bssid", NEXTARG, 0, setifbssid }, 428 { "-bssid", -1, 0, setifbssid }, 429 { "nwkey", NEXTARG, 0, setifnwkey }, 430 { "-nwkey", -1, 0, setifnwkey }, 431 { "wpa", 1, 0, setifwpa }, 432 { "-wpa", 0, 0, setifwpa }, 433 { "wpaakms", NEXTARG, 0, setifwpaakms }, 434 { "wpaciphers", NEXTARG, 0, setifwpaciphers }, 435 { "wpagroupcipher", NEXTARG, 0, setifwpagroupcipher }, 436 { "wpaprotos", NEXTARG, 0, setifwpaprotos }, 437 { "wpakey", NEXTARG, 0, setifwpakey }, 438 { "-wpakey", -1, 0, setifwpakey }, 439 { "chan", NEXTARG0, 0, setifchan }, 440 { "-chan", -1, 0, setifchan }, 441 { "scan", NEXTARG0, 0, setifscan }, 442 { "broadcast", NEXTARG, 0, setifbroadaddr }, 443 { "prefixlen", NEXTARG, 0, setifprefixlen}, 444 { "vnetid", NEXTARG, 0, setvnetid }, 445 { "-vnetid", 0, 0, delvnetid }, 446 { "parent", NEXTARG, 0, setifparent }, 447 { "-parent", 1, 0, delifparent }, 448 { "vlan", NEXTARG, 0, setvnetid }, 449 { "-vlan", 0, 0, delvnetid }, 450 { "vlandev", NEXTARG, 0, setifparent }, 451 { "-vlandev", 1, 0, delifparent }, 452 { "group", NEXTARG, 0, setifgroup }, 453 { "-group", NEXTARG, 0, unsetifgroup }, 454 { "autoconf", 1, 0, setautoconf }, 455 { "-autoconf", -1, 0, setautoconf }, 456 { "trunkport", NEXTARG, 0, settrunkport }, 457 { "-trunkport", NEXTARG, 0, unsettrunkport }, 458 { "trunkproto", NEXTARG, 0, settrunkproto }, 459 { "lacpmode", NEXTARG, 0, settrunklacpmode }, 460 { "lacptimeout", NEXTARG, 0, settrunklacptimeout }, 461 { "anycast", IN6_IFF_ANYCAST, 0, setia6flags }, 462 { "-anycast", -IN6_IFF_ANYCAST, 0, setia6flags }, 463 { "tentative", IN6_IFF_TENTATIVE, 0, setia6flags }, 464 { "-tentative", -IN6_IFF_TENTATIVE, 0, setia6flags }, 465 { "pltime", NEXTARG, 0, setia6pltime }, 466 { "vltime", NEXTARG, 0, setia6vltime }, 467 { "eui64", 0, 0, setia6eui64 }, 468 { "temporary", 1, 0, settemporary }, 469 { "-temporary", -1, 0, settemporary }, 470 { "soii", -IFXF_INET6_NOSOII, 0, setifxflags }, 471 { "-soii", IFXF_INET6_NOSOII, 0, setifxflags }, 472 { "monitor", IFXF_MONITOR, 0, setifxflags }, 473 { "-monitor", -IFXF_MONITOR, 0, setifxflags }, 474 { "tcplro", IFXF_LRO, 0, setifxflags }, 475 { "-tcplro", -IFXF_LRO, 0, setifxflags }, 476#ifndef SMALL 477 { "hwfeatures", NEXTARG0, 0, printifhwfeatures }, 478 { "metric", NEXTARG, 0, setifmetric }, 479 { "powersave", NEXTARG0, 0, setifpowersave }, 480 { "-powersave", -1, 0, setifpowersave }, 481 { "priority", NEXTARG, 0, setifpriority }, 482 { "rtlabel", NEXTARG, 0, setifrtlabel }, 483 { "-rtlabel", -1, 0, setifrtlabel }, 484 { "rdomain", NEXTARG, 0, setrdomain }, 485 { "-rdomain", 0, 0, unsetrdomain }, 486 { "staticarp", IFF_STATICARP, 0, setifflags }, 487 { "-staticarp", -IFF_STATICARP, 0, setifflags }, 488 { "mpls", IFXF_MPLS, 0, setifxflags }, 489 { "-mpls", -IFXF_MPLS, 0, setifxflags }, 490 { "mplslabel", NEXTARG, 0, setmplslabel }, 491 { "-mplslabel", 0, 0, unsetmplslabel }, 492 { "pwecw", 0, 0, setpwe3cw }, 493 { "-pwecw", 0, 0, unsetpwe3cw }, 494 { "pwefat", 0, 0, setpwe3fat }, 495 { "-pwefat", 0, 0, unsetpwe3fat }, 496 { "pweneighbor", NEXTARG2, 0, NULL, setpwe3neighbor }, 497 { "-pweneighbor", 0, 0, unsetpwe3neighbor }, 498 { "advbase", NEXTARG, 0, setcarp_advbase }, 499 { "advskew", NEXTARG, 0, setcarp_advskew }, 500 { "carppeer", NEXTARG, 0, setcarppeer }, 501 { "-carppeer", 1, 0, unsetcarppeer }, 502 { "pass", NEXTARG, 0, setcarp_passwd }, 503 { "vhid", NEXTARG, 0, setcarp_vhid }, 504 { "state", NEXTARG, 0, setcarp_state }, 505 { "carpdev", NEXTARG, 0, setcarpdev }, 506 { "carpnodes", NEXTARG, 0, setcarp_nodes }, 507 { "balancing", NEXTARG, 0, setcarp_balancing }, 508 { "syncdev", NEXTARG, 0, setpfsync_syncdev }, 509 { "-syncdev", 1, 0, unsetpfsync_syncdev }, 510 { "syncif", NEXTARG, 0, setpfsync_syncdev }, 511 { "-syncif", 1, 0, unsetpfsync_syncdev }, 512 { "syncpeer", NEXTARG, 0, setpfsync_syncpeer }, 513 { "-syncpeer", 1, 0, unsetpfsync_syncpeer }, 514 { "maxupd", NEXTARG, 0, setpfsync_maxupd }, 515 { "defer", 1, 0, setpfsync_defer }, 516 { "-defer", 0, 0, setpfsync_defer }, 517 { "tunnel", NEXTARG2, 0, NULL, settunnel }, 518 { "tunneladdr", NEXTARG, 0, settunneladdr }, 519 { "-tunnel", 0, 0, deletetunnel }, 520 { "tunneldomain", NEXTARG, 0, settunnelinst }, 521 { "-tunneldomain", 0, 0, unsettunnelinst }, 522 { "tunnelttl", NEXTARG, 0, settunnelttl }, 523 { "tunneldf", 0, 0, settunneldf }, 524 { "-tunneldf", 0, 0, settunnelnodf }, 525 { "tunnelecn", 0, 0, settunnelecn }, 526 { "-tunnelecn", 0, 0, settunnelnoecn }, 527 { "vnetflowid", 0, 0, setvnetflowid }, 528 { "-vnetflowid", 0, 0, delvnetflowid }, 529 { "txprio", NEXTARG, 0, settxprio }, 530 { "rxprio", NEXTARG, 0, setrxprio }, 531 { "pppoedev", NEXTARG, 0, setpppoe_dev }, 532 { "pppoesvc", NEXTARG, 0, setpppoe_svc }, 533 { "-pppoesvc", 1, 0, setpppoe_svc }, 534 { "pppoeac", NEXTARG, 0, setpppoe_ac }, 535 { "-pppoeac", 1, 0, setpppoe_ac }, 536 { "authproto", NEXTARG, 0, setspppproto }, 537 { "authname", NEXTARG, 0, setspppname }, 538 { "authkey", NEXTARG, 0, setspppkey }, 539 { "peerproto", NEXTARG, 0, setsppppeerproto }, 540 { "peername", NEXTARG, 0, setsppppeername }, 541 { "peerkey", NEXTARG, 0, setsppppeerkey }, 542 { "peerflag", NEXTARG, 0, setsppppeerflag }, 543 { "-peerflag", NEXTARG, 0, unsetsppppeerflag }, 544 { "nwflag", NEXTARG, 0, setifnwflag }, 545 { "-nwflag", NEXTARG, 0, unsetifnwflag }, 546 { "flowsrc", NEXTARG, 0, setpflow_sender }, 547 { "-flowsrc", 1, 0, unsetpflow_sender }, 548 { "flowdst", NEXTARG, 0, setpflow_receiver }, 549 { "-flowdst", 1, 0, unsetpflow_receiver }, 550 { "pflowproto", NEXTARG, 0, setpflowproto }, 551 { "-inet", AF_INET, 0, removeaf }, 552 { "-inet6", AF_INET6, 0, removeaf }, 553 { "keepalive", NEXTARG2, 0, NULL, setkeepalive }, 554 { "-keepalive", 1, 0, unsetkeepalive }, 555 { "add", NEXTARG, 0, bridge_add }, 556 { "del", NEXTARG, 0, bridge_delete }, 557 { "addspan", NEXTARG, 0, bridge_addspan }, 558 { "delspan", NEXTARG, 0, bridge_delspan }, 559 { "discover", NEXTARG, 0, setdiscover }, 560 { "-discover", NEXTARG, 0, unsetdiscover }, 561 { "blocknonip", NEXTARG, 0, setblocknonip }, 562 { "-blocknonip",NEXTARG, 0, unsetblocknonip }, 563 { "learn", NEXTARG, 0, setlearn }, 564 { "-learn", NEXTARG, 0, unsetlearn }, 565 { "stp", NEXTARG, 0, setstp }, 566 { "-stp", NEXTARG, 0, unsetstp }, 567 { "edge", NEXTARG, 0, setedge }, 568 { "-edge", NEXTARG, 0, unsetedge }, 569 { "autoedge", NEXTARG, 0, setautoedge }, 570 { "-autoedge", NEXTARG, 0, unsetautoedge }, 571 { "protected", NEXTARG2, 0, NULL, bridge_protect }, 572 { "-protected", NEXTARG, 0, bridge_unprotect }, 573 { "ptp", NEXTARG, 0, setptp }, 574 { "-ptp", NEXTARG, 0, unsetptp }, 575 { "autoptp", NEXTARG, 0, setautoptp }, 576 { "-autoptp", NEXTARG, 0, unsetautoptp }, 577 { "flush", 0, 0, bridge_flush }, 578 { "flushall", 0, 0, bridge_flushall }, 579 { "static", NEXTARG2, 0, NULL, bridge_addaddr }, 580 { "endpoint", NEXTARG2, 0, NULL, bridge_addendpoint }, 581 { "deladdr", NEXTARG, 0, bridge_deladdr }, 582 { "maxaddr", NEXTARG, 0, bridge_maxaddr }, 583 { "addr", 0, 0, bridge_addrs }, 584 { "hellotime", NEXTARG, 0, bridge_hellotime }, 585 { "fwddelay", NEXTARG, 0, bridge_fwddelay }, 586 { "maxage", NEXTARG, 0, bridge_maxage }, 587 { "proto", NEXTARG, 0, bridge_proto }, 588 { "ifpriority", NEXTARG2, 0, NULL, bridge_ifprio }, 589 { "ifcost", NEXTARG2, 0, NULL, bridge_ifcost }, 590 { "-ifcost", NEXTARG, 0, bridge_noifcost }, 591 { "timeout", NEXTARG, 0, bridge_timeout }, 592 { "holdcnt", NEXTARG, 0, bridge_holdcnt }, 593 { "spanpriority", NEXTARG, 0, bridge_priority }, 594 { "ipdst", NEXTARG, 0, setifipdst }, 595#if 0 596 /* XXX `rule` special-cased below */ 597 { "rule", 0, 0, bridge_rule }, 598#endif 599 { "rules", NEXTARG, 0, bridge_rules }, 600 { "rulefile", NEXTARG, 0, bridge_rulefile }, 601 { "flushrule", NEXTARG, 0, bridge_flushrule }, 602 { "description", NEXTARG, 0, setifdesc }, 603 { "descr", NEXTARG, 0, setifdesc }, 604 { "-description", 1, 0, unsetifdesc }, 605 { "-descr", 1, 0, unsetifdesc }, 606 { "wol", IFXF_WOL, 0, setifxflags }, 607 { "-wol", -IFXF_WOL, 0, setifxflags }, 608 { "pin", NEXTARG, 0, umb_setpin }, 609 { "chgpin", NEXTARG2, 0, NULL, umb_chgpin }, 610 { "puk", NEXTARG2, 0, NULL, umb_puk }, 611 { "apn", NEXTARG, 0, umb_apn }, 612 { "-apn", -1, 0, umb_apn }, 613 { "class", NEXTARG0, 0, umb_setclass }, 614 { "-class", -1, 0, umb_setclass }, 615 { "roaming", 1, 0, umb_roaming }, 616 { "-roaming", 0, 0, umb_roaming }, 617 { "patch", NEXTARG, 0, setpair }, 618 { "-patch", 1, 0, unsetpair }, 619 { "addlocal", NEXTARG, 0, addlocal }, 620 { "transceiver", NEXTARG0, 0, transceiver }, 621 { "sff", NEXTARG0, 0, transceiver }, 622 { "sffdump", 0, 0, transceiverdump }, 623 624 { "wgpeer", NEXTARG, A_WIREGUARD, setwgpeer}, 625 { "wgdescription", NEXTARG, A_WIREGUARD, setwgpeerdesc}, 626 { "wgdescr", NEXTARG, A_WIREGUARD, setwgpeerdesc}, 627 { "wgendpoint", NEXTARG2, A_WIREGUARD, NULL, setwgpeerep}, 628 { "wgaip", NEXTARG, A_WIREGUARD, setwgpeeraip}, 629 { "wgpsk", NEXTARG, A_WIREGUARD, setwgpeerpsk}, 630 { "wgpka", NEXTARG, A_WIREGUARD, setwgpeerpka}, 631 { "wgport", NEXTARG, A_WIREGUARD, setwgport}, 632 { "wgkey", NEXTARG, A_WIREGUARD, setwgkey}, 633 { "wgrtable", NEXTARG, A_WIREGUARD, setwgrtable}, 634 { "-wgpeer", NEXTARG, A_WIREGUARD, unsetwgpeer}, 635 { "-wgpsk", 0, A_WIREGUARD, unsetwgpeerpsk}, 636 { "-wgdescription", 0, A_WIREGUARD, unsetwgpeerdesc}, 637 { "-wgdescr", 0, A_WIREGUARD, unsetwgpeerdesc}, 638 { "-wgpeerall", 0, A_WIREGUARD, unsetwgpeerall}, 639 640#else /* SMALL */ 641 { "powersave", NEXTARG0, 0, setignore }, 642 { "priority", NEXTARG, 0, setignore }, 643 { "rtlabel", NEXTARG, 0, setignore }, 644 { "mpls", IFXF_MPLS, 0, setignore }, 645 { "nwflag", NEXTARG, 0, setignore }, 646 { "rdomain", NEXTARG, 0, setignore }, 647 { "-inet", AF_INET, 0, removeaf }, 648 { "-inet6", AF_INET6, 0, removeaf }, 649 { "description", NEXTARG, 0, setignore }, 650 { "descr", NEXTARG, 0, setignore }, 651 { "wol", IFXF_WOL, 0, setignore }, 652 { "-wol", -IFXF_WOL, 0, setignore }, 653#endif /* SMALL */ 654#if 0 655 /* XXX `create' special-cased below */ 656 { "create", 0, 0, clone_create } , 657#endif 658 { "destroy", 0, 0, clone_destroy } , 659 { "link0", IFF_LINK0, 0, setifflags } , 660 { "-link0", -IFF_LINK0, 0, setifflags } , 661 { "link1", IFF_LINK1, 0, setifflags } , 662 { "-link1", -IFF_LINK1, 0, setifflags } , 663 { "link2", IFF_LINK2, 0, setifflags } , 664 { "-link2", -IFF_LINK2, 0, setifflags } , 665 { "media", NEXTARG0, A_MEDIA, setmedia }, 666 { "mediaopt", NEXTARG, A_MEDIAOPTSET, setmediaopt }, 667 { "-mediaopt", NEXTARG, A_MEDIAOPTCLR, unsetmediaopt }, 668 { "mode", NEXTARG, A_MEDIAMODE, setmediamode }, 669 { "-mode", 0, A_MEDIAMODE, unsetmediamode }, 670 { "instance", NEXTARG, A_MEDIAINST, setmediainst }, 671 { "inst", NEXTARG, A_MEDIAINST, setmediainst }, 672 { "lladdr", NEXTARG, 0, setiflladdr }, 673 { "llprio", NEXTARG, 0, setifllprio }, 674 { NULL, /*src*/ 0, 0, setifaddr }, 675 { NULL, /*dst*/ 0, 0, setifdstaddr }, 676 { NULL, /*illegal*/0, 0, NULL }, 677}; 678 679#define IFFBITS \ 680 "\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6STATICARP" \ 681 "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" \ 682 "\15LINK0\16LINK1\17LINK2\20MULTICAST" \ 683 "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII" \ 684 "\30AUTOCONF4" "\31MONITOR" "\32LRO" 685 686int getinfo(struct ifreq *, int); 687void getsock(int); 688void printgroupattribs(char *); 689void printif(char *, int); 690void printb_status(unsigned short, unsigned char *); 691const char *get_linkstate(int, int); 692void status(int, struct sockaddr_dl *, int, int); 693__dead void usage(void); 694const char *get_string(const char *, const char *, u_int8_t *, int *); 695int len_string(const u_int8_t *, int); 696int print_string(const u_int8_t *, int); 697char *sec2str(time_t); 698 699const char *get_media_type_string(uint64_t); 700const char *get_media_subtype_string(uint64_t); 701uint64_t get_media_mode(uint64_t, const char *); 702uint64_t get_media_subtype(uint64_t, const char *); 703uint64_t get_media_options(uint64_t, const char *); 704uint64_t lookup_media_word(const struct ifmedia_description *, uint64_t, 705 const char *); 706void print_media_word(uint64_t, int, int); 707void process_media_commands(void); 708void init_current_media(void); 709 710void process_join_commands(void); 711 712void process_wg_commands(void); 713 714void in_status(int); 715void in_getaddr(const char *, int); 716void in_getprefix(const char *, int); 717void in6_fillscopeid(struct sockaddr_in6 *); 718void in6_alias(struct in6_ifreq *); 719void in6_status(int); 720void in6_getaddr(const char *, int); 721void in6_getprefix(const char *, int); 722void ieee80211_status(void); 723void join_status(void); 724void ieee80211_listchans(void); 725void ieee80211_listnodes(void); 726void ieee80211_printnode(struct ieee80211_nodereq *); 727u_int getwpacipher(const char *); 728void print_cipherset(u_int32_t); 729 730void spppauthinfo(struct sauthreq *, int); 731void spppdnsinfo(struct sdnsreq *); 732 733/* Known address families */ 734const struct afswtch { 735 char *af_name; 736 short af_af; 737 void (*af_status)(int); 738 void (*af_getaddr)(const char *, int); 739 void (*af_getprefix)(const char *, int); 740 u_long af_difaddr; 741 u_long af_aifaddr; 742 caddr_t af_ridreq; 743 caddr_t af_addreq; 744} afs[] = { 745#define C(x) ((caddr_t) &x) 746 { "inet", AF_INET, in_status, in_getaddr, in_getprefix, 747 SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(in_addreq) }, 748 { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix, 749 SIOCDIFADDR_IN6, SIOCAIFADDR_IN6, C(in6_ridreq), C(in6_addreq) }, 750 { 0, 0, 0, 0 } 751}; 752 753const struct afswtch *afp; /*the address family being set or asked about*/ 754 755char joinname[IEEE80211_NWID_LEN]; 756size_t joinlen; 757char nwidname[IEEE80211_NWID_LEN]; 758size_t nwidlen; 759 760int ifaliases = 0; 761int aflag = 0; 762 763int 764main(int argc, char *argv[]) 765{ 766 const struct afswtch *rafp = NULL; 767 int create = 0; 768 int Cflag = 0; 769 int gflag = 0; 770 int found_rulefile = 0; 771 int i; 772 773 /* If no args at all, print all interfaces. */ 774 if (argc < 2) { 775 /* no filesystem visibility */ 776 if (unveil("/", "") == -1) 777 err(1, "unveil /"); 778 if (unveil(NULL, NULL) == -1) 779 err(1, "unveil"); 780 aflag = 1; 781 printif(NULL, 0); 782 return (0); 783 } 784 argc--, argv++; 785 if (*argv[0] == '-') { 786 int nomore = 0; 787 788 for (i = 1; argv[0][i]; i++) { 789 switch (argv[0][i]) { 790 case 'a': 791 aflag = 1; 792 nomore = 1; 793 break; 794 case 'A': 795 aflag = 1; 796 ifaliases = 1; 797 nomore = 1; 798 break; 799 case 'g': 800 gflag = 1; 801 break; 802 case 'C': 803 Cflag = 1; 804 nomore = 1; 805 break; 806 case 'M': 807 if (argv[1] == NULL) 808 usage(); 809 exit(findmac(argv[1])); 810 break; 811 default: 812 usage(); 813 break; 814 } 815 } 816 if (nomore == 0) { 817 argc--, argv++; 818 if (argc < 1) 819 usage(); 820 if (strlcpy(ifname, *argv, sizeof(ifname)) >= IFNAMSIZ) 821 errx(1, "interface name '%s' too long", *argv); 822 } 823 } else if (strlcpy(ifname, *argv, sizeof(ifname)) >= IFNAMSIZ) 824 errx(1, "interface name '%s' too long", *argv); 825 argc--, argv++; 826 827 for (i = 0; i < argc; i++) { 828 if (strcmp(argv[i], "rulefile") == 0) { 829 found_rulefile = 1; 830 break; 831 } 832 } 833 834 if (!found_rulefile) { 835 if (unveil(_PATH_RESCONF, "r") == -1) 836 err(1, "unveil %s", _PATH_RESCONF); 837 if (unveil(_PATH_HOSTS, "r") == -1) 838 err(1, "unveil %s", _PATH_HOSTS); 839 if (unveil(_PATH_SERVICES, "r") == -1) 840 err(1, "unveil %s", _PATH_SERVICES); 841 if (unveil(NULL, NULL) == -1) 842 err(1, "unveil"); 843 } 844 845 if (argc > 0) { 846 for (afp = rafp = afs; rafp->af_name; rafp++) 847 if (strcmp(rafp->af_name, *argv) == 0) { 848 afp = rafp; 849 argc--; 850 argv++; 851 break; 852 } 853 rafp = afp; 854 af = ifr.ifr_addr.sa_family = rafp->af_af; 855 } 856 if (Cflag) { 857 if (argc > 0 || aflag) 858 usage(); 859 list_cloners(); 860 return (0); 861 } 862 if (gflag) { 863 if (argc == 0) 864 printgroupattribs(ifname); 865 else 866 setgroupattribs(ifname, argc, argv); 867 return (0); 868 } 869 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 870 871 /* initialization */ 872 in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 873 in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 874 875 /* 876 * NOTE: We must special-case the `create' command right 877 * here as we would otherwise fail in getinfo(). 878 */ 879 if (argc > 0 && strcmp(argv[0], "create") == 0) { 880 clone_create(argv[0], 0); 881 argc--, argv++; 882 if (argc == 0) 883 return (0); 884 } 885 if (aflag == 0) { 886 create = (argc > 0) && strcmp(argv[0], "destroy") != 0; 887 (void)getinfo(&ifr, create); 888 } 889 890 if (argc != 0 && af == AF_INET6) 891 addaf(ifname, AF_INET6); 892 893 while (argc > 0) { 894 const struct cmd *p; 895 896 for (p = cmds; p->c_name; p++) 897 if (strcmp(*argv, p->c_name) == 0) 898 break; 899#ifndef SMALL 900 if (strcmp(*argv, "rule") == 0) { 901 argc--, argv++; 902 return bridge_rule(argc, argv, -1); 903 } 904#endif 905 if (p->c_name == 0 && setaddr) 906 for (i = setaddr; i > 0; i--) { 907 p++; 908 if (p->c_func == NULL) 909 errx(1, "%s: bad value", *argv); 910 } 911 if (p->c_func || p->c_func2) { 912 if (p->c_parameter == NEXTARG0) { 913 const struct cmd *p0; 914 int noarg = 1; 915 916 if (argv[1]) { 917 for (p0 = cmds; p0->c_name; p0++) 918 if (strcmp(argv[1], 919 p0->c_name) == 0) { 920 noarg = 0; 921 break; 922 } 923 } else 924 noarg = 0; 925 926 if (noarg == 0) 927 (*p->c_func)(NULL, 0); 928 else 929 goto nextarg; 930 } else if (p->c_parameter == NEXTARG) { 931nextarg: 932 if (argv[1] == NULL) 933 errx(1, "'%s' requires argument", 934 p->c_name); 935 (*p->c_func)(argv[1], 0); 936 argc--, argv++; 937 actions = actions | A_SILENT | p->c_action; 938 } else if (p->c_parameter == NEXTARG2) { 939 if ((argv[1] == NULL) || 940 (argv[2] == NULL)) 941 errx(1, "'%s' requires 2 arguments", 942 p->c_name); 943 (*p->c_func2)(argv[1], argv[2]); 944 argc -= 2; 945 argv += 2; 946 actions = actions | A_SILENT | p->c_action; 947 } else { 948 (*p->c_func)(*argv, p->c_parameter); 949 actions = actions | A_SILENT | p->c_action; 950 } 951 } 952 argc--, argv++; 953 } 954 955 if (argc == 0 && actions == 0) { 956 printif(ifr.ifr_name, aflag ? ifaliases : 1); 957 return (0); 958 } 959 960#ifndef SMALL 961 process_wg_commands(); 962#endif 963 964 process_join_commands(); 965 966 /* Process any media commands that may have been issued. */ 967 process_media_commands(); 968 969 if (af == AF_INET6 && explicit_prefix == 0) { 970 /* 971 * Aggregatable address architecture defines all prefixes 972 * are 64. So, it is convenient to set prefixlen to 64 if 973 * it is not specified. If we are setting a destination 974 * address on a point-to-point interface, 128 is required. 975 */ 976 if (setipdst && (flags & IFF_POINTOPOINT)) 977 setifprefixlen("128", 0); 978 else 979 setifprefixlen("64", 0); 980 /* in6_getprefix("64", MASK) if MASK is available here... */ 981 } 982 983 if (clearaddr) { 984 (void) strlcpy(rafp->af_ridreq, ifname, sizeof(ifr.ifr_name)); 985 if (ioctl(sock, rafp->af_difaddr, rafp->af_ridreq) == -1) { 986 if (errno == EADDRNOTAVAIL && (doalias >= 0)) { 987 /* means no previous address for interface */ 988 } else 989 err(1, "SIOCDIFADDR"); 990 } 991 } 992 if (newaddr) { 993 (void) strlcpy(rafp->af_addreq, ifname, sizeof(ifr.ifr_name)); 994 if (ioctl(sock, rafp->af_aifaddr, rafp->af_addreq) == -1) 995 err(1, "SIOCAIFADDR"); 996 } 997 return (0); 998} 999 1000void 1001getsock(int naf) 1002{ 1003 static int oaf = -1; 1004 1005 if (oaf == naf) 1006 return; 1007 if (oaf != -1) 1008 close(sock); 1009 sock = socket(naf, SOCK_DGRAM, 0); 1010 if (sock == -1) 1011 oaf = -1; 1012 else 1013 oaf = naf; 1014} 1015 1016int 1017getinfo(struct ifreq *ifr, int create) 1018{ 1019 1020 getsock(af); 1021 if (sock == -1) 1022 err(1, "socket"); 1023 if (!isdigit((unsigned char)ifname[strlen(ifname) - 1])) 1024 return (-1); /* ignore groups here */ 1025 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)ifr) == -1) { 1026 int oerrno = errno; 1027 1028 if (!create) 1029 return (-1); 1030 if (ioctl(sock, SIOCIFCREATE, (caddr_t)ifr) == -1) { 1031 errno = oerrno; 1032 return (-1); 1033 } 1034 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)ifr) == -1) 1035 return (-1); 1036 } 1037 flags = ifr->ifr_flags & 0xffff; 1038 if (ioctl(sock, SIOCGIFXFLAGS, (caddr_t)ifr) == -1) 1039 ifr->ifr_flags = 0; 1040 xflags = ifr->ifr_flags; 1041 if (ioctl(sock, SIOCGIFMETRIC, (caddr_t)ifr) == -1) 1042 metric = 0; 1043 else 1044 metric = ifr->ifr_metric; 1045 if (ioctl(sock, SIOCGIFMTU, (caddr_t)ifr) == -1) 1046 mtu = 0; 1047 else 1048 mtu = ifr->ifr_mtu; 1049#ifndef SMALL 1050 if (ioctl(sock, SIOCGIFRDOMAIN, (caddr_t)ifr) == -1) 1051 rdomainid = 0; 1052 else 1053 rdomainid = ifr->ifr_rdomainid; 1054#endif 1055 if (ioctl(sock, SIOCGIFLLPRIO, (caddr_t)ifr) == -1) 1056 llprio = 0; 1057 else 1058 llprio = ifr->ifr_llprio; 1059 1060 return (0); 1061} 1062 1063int 1064printgroup(char *groupname, int ifaliases) 1065{ 1066 struct ifgroupreq ifgr; 1067 struct ifg_req *ifg; 1068 int len, cnt = 0; 1069 1070 getsock(AF_INET); 1071 bzero(&ifgr, sizeof(ifgr)); 1072 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); 1073 if (ioctl(sock, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { 1074 if (errno == EINVAL || errno == ENOTTY || 1075 errno == ENOENT) 1076 return (-1); 1077 else 1078 err(1, "%s: SIOCGIFGMEMB", ifgr.ifgr_name); 1079 } 1080 1081 len = ifgr.ifgr_len; 1082 if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 1083 err(1, "printgroup"); 1084 if (ioctl(sock, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 1085 err(1, "%s: SIOCGIFGMEMB", ifgr.ifgr_name); 1086 1087 for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 1088 ifg++) { 1089 len -= sizeof(struct ifg_req); 1090 printif(ifg->ifgrq_member, ifaliases); 1091 cnt++; 1092 } 1093 free(ifgr.ifgr_groups); 1094 1095 return (cnt); 1096} 1097 1098void 1099printgroupattribs(char *groupname) 1100{ 1101 struct ifgroupreq ifgr; 1102 1103 getsock(AF_INET); 1104 bzero(&ifgr, sizeof(ifgr)); 1105 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); 1106 if (ioctl(sock, SIOCGIFGATTR, (caddr_t)&ifgr) == -1) 1107 err(1, "%s: SIOCGIFGATTR", ifgr.ifgr_name); 1108 1109 printf("%s:", groupname); 1110 printf(" carp demote count %d", ifgr.ifgr_attrib.ifg_carp_demoted); 1111 printf("\n"); 1112} 1113 1114void 1115setgroupattribs(char *groupname, int argc, char *argv[]) 1116{ 1117 const char *errstr; 1118 char *p = argv[0]; 1119 int neg = 1; 1120 1121 struct ifgroupreq ifgr; 1122 1123 getsock(AF_INET); 1124 bzero(&ifgr, sizeof(ifgr)); 1125 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); 1126 1127 if (argc > 1) { 1128 neg = strtonum(argv[1], 0, 128, &errstr); 1129 if (errstr) 1130 errx(1, "%s: invalid carp demotion: %s", ifgr.ifgr_name, 1131 errstr); 1132 } 1133 1134 if (p[0] == '-') { 1135 neg = neg * -1; 1136 p++; 1137 } 1138 if (!strcmp(p, "carpdemote")) 1139 ifgr.ifgr_attrib.ifg_carp_demoted = neg; 1140 else 1141 usage(); 1142 1143 if (ioctl(sock, SIOCSIFGATTR, (caddr_t)&ifgr) == -1) 1144 err(1, "%s: SIOCSIFGATTR", ifgr.ifgr_name); 1145} 1146 1147void 1148printif(char *name, int ifaliases) 1149{ 1150 struct ifaddrs *ifap, *ifa; 1151 struct if_data *ifdata; 1152 const char *namep; 1153 char *oname = NULL; 1154 struct ifreq *ifrp; 1155 int count = 0, noinet = 1; 1156 size_t nlen = 0; 1157 1158 if (aflag) 1159 name = NULL; 1160 if (name) { 1161 if ((oname = strdup(name)) == NULL) 1162 err(1, "strdup"); 1163 nlen = strlen(oname); 1164 /* is it a group? */ 1165 if (nlen && !isdigit((unsigned char)oname[nlen - 1])) 1166 if (printgroup(oname, ifaliases) != -1) { 1167 free(oname); 1168 return; 1169 } 1170 } 1171 1172 if (getifaddrs(&ifap) != 0) 1173 err(1, "getifaddrs"); 1174 1175 namep = NULL; 1176 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1177 if (oname) { 1178 if (nlen && isdigit((unsigned char)oname[nlen - 1])) { 1179 /* must have exact match */ 1180 if (strcmp(oname, ifa->ifa_name) != 0) 1181 continue; 1182 } else { 1183 /* partial match OK if it ends w/ digit */ 1184 if (strncmp(oname, ifa->ifa_name, nlen) != 0 || 1185 !isdigit((unsigned char)ifa->ifa_name[nlen])) 1186 continue; 1187 } 1188 } 1189 /* quickhack: sizeof(ifr) < sizeof(ifr6) */ 1190 if (ifa->ifa_addr != NULL && 1191 ifa->ifa_addr->sa_family == AF_INET6) { 1192 memset(&ifr6, 0, sizeof(ifr6)); 1193 memcpy(&ifr6.ifr_addr, ifa->ifa_addr, 1194 MINIMUM(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len)); 1195 ifrp = (struct ifreq *)&ifr6; 1196 } else if (ifa->ifa_addr != NULL) { 1197 memset(&ifr, 0, sizeof(ifr)); 1198 memcpy(&ifr.ifr_addr, ifa->ifa_addr, 1199 MINIMUM(sizeof(ifr.ifr_addr), ifa->ifa_addr->sa_len)); 1200 ifrp = 𝔦 1201 } 1202 strlcpy(ifname, ifa->ifa_name, sizeof(ifname)); 1203 strlcpy(ifrp->ifr_name, ifa->ifa_name, sizeof(ifrp->ifr_name)); 1204 1205 if (ifa->ifa_addr != NULL && 1206 ifa->ifa_addr->sa_family == AF_LINK) { 1207 namep = ifa->ifa_name; 1208 if (getinfo(ifrp, 0) < 0) 1209 continue; 1210 ifdata = ifa->ifa_data; 1211 status(1, (struct sockaddr_dl *)ifa->ifa_addr, 1212 ifdata->ifi_link_state, ifaliases); 1213 count++; 1214 noinet = 1; 1215 continue; 1216 } 1217 1218 if (!namep || !strcmp(namep, ifa->ifa_name)) { 1219 const struct afswtch *p; 1220 1221 if (ifa->ifa_addr == NULL || 1222 (ifa->ifa_addr->sa_family == AF_INET && 1223 ifaliases == 0 && noinet == 0)) 1224 continue; 1225 if ((p = afp) != NULL) { 1226 if (ifa->ifa_addr->sa_family == p->af_af) 1227 p->af_status(1); 1228 } else { 1229 for (p = afs; p->af_name; p++) { 1230 if (ifa->ifa_addr->sa_family == 1231 p->af_af) 1232 p->af_status(0); 1233 } 1234 } 1235 count++; 1236 if (ifa->ifa_addr->sa_family == AF_INET) 1237 noinet = 0; 1238 continue; 1239 } 1240 } 1241 freeifaddrs(ifap); 1242 free(oname); 1243 if (count == 0) { 1244 fprintf(stderr, "%s: no such interface\n", ifname); 1245 exit(1); 1246 } 1247} 1248 1249void 1250clone_create(const char *addr, int param) 1251{ 1252 1253 /* We're called early... */ 1254 getsock(AF_INET); 1255 1256 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1257 if (ioctl(sock, SIOCIFCREATE, &ifr) == -1) 1258 err(1, "%s: SIOCIFCREATE", ifr.ifr_name); 1259} 1260 1261void 1262clone_destroy(const char *addr, int param) 1263{ 1264 1265 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1266 if (ioctl(sock, SIOCIFDESTROY, &ifr) == -1) 1267 err(1, "%s: SIOCIFDESTROY", ifr.ifr_name); 1268} 1269 1270struct if_clonereq * 1271get_cloners(void) 1272{ 1273 static struct if_clonereq ifcr; 1274 1275 memset(&ifcr, 0, sizeof(ifcr)); 1276 1277 getsock(AF_INET); 1278 1279 if (ioctl(sock, SIOCIFGCLONERS, &ifcr) == -1) 1280 err(1, "SIOCIFGCLONERS for count"); 1281 1282 if ((ifcr.ifcr_buffer = calloc(ifcr.ifcr_total, IFNAMSIZ)) == NULL) 1283 err(1, "unable to allocate cloner name buffer"); 1284 ifcr.ifcr_count = ifcr.ifcr_total; 1285 1286 if (ioctl(sock, SIOCIFGCLONERS, &ifcr) == -1) 1287 err(1, "SIOCIFGCLONERS for names"); 1288 1289 /* 1290 * In case some disappeared in the mean time, clamp it down. 1291 */ 1292 if (ifcr.ifcr_count > ifcr.ifcr_total) 1293 ifcr.ifcr_count = ifcr.ifcr_total; 1294 1295 return &ifcr; 1296} 1297 1298void 1299list_cloners(void) 1300{ 1301 struct if_clonereq *ifcr; 1302 char *cp, *buf; 1303 int idx; 1304 1305 ifcr = get_cloners(); 1306 buf = ifcr->ifcr_buffer; 1307 1308 qsort(buf, ifcr->ifcr_count, IFNAMSIZ, 1309 (int(*)(const void *, const void *))strcmp); 1310 1311 for (cp = buf, idx = 0; idx < ifcr->ifcr_count; idx++, cp += IFNAMSIZ) { 1312 if (idx > 0) 1313 putchar(' '); 1314 printf("%s", cp); 1315 } 1316 1317 putchar('\n'); 1318 free(ifcr->ifcr_buffer); 1319} 1320 1321#define RIDADDR 0 1322#define ADDR 1 1323#define MASK 2 1324#define DSTADDR 3 1325 1326void 1327setifaddr(const char *addr, int param) 1328{ 1329 /* 1330 * Delay the ioctl to set the interface addr until flags are all set. 1331 * The address interpretation may depend on the flags, 1332 * and the flags may change when the address is set. 1333 */ 1334 setaddr++; 1335 if (doalias >= 0) 1336 newaddr = 1; 1337 if (doalias == 0) 1338 clearaddr = 1; 1339 afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR)); 1340} 1341 1342#ifndef SMALL 1343void 1344setifrtlabel(const char *label, int d) 1345{ 1346 if (d != 0) 1347 ifr.ifr_data = (caddr_t)(const char *)""; 1348 else 1349 ifr.ifr_data = (caddr_t)label; 1350 if (ioctl(sock, SIOCSIFRTLABEL, &ifr) == -1) 1351 warn("SIOCSIFRTLABEL"); 1352} 1353#endif 1354 1355void 1356setifnetmask(const char *addr, int ignored) 1357{ 1358 afp->af_getaddr(addr, MASK); 1359 explicit_prefix = 1; 1360} 1361 1362void 1363setifbroadaddr(const char *addr, int ignored) 1364{ 1365 afp->af_getaddr(addr, DSTADDR); 1366} 1367 1368#ifndef SMALL 1369void 1370setifdesc(const char *val, int ignored) 1371{ 1372 ifr.ifr_data = (caddr_t)val; 1373 if (ioctl(sock, SIOCSIFDESCR, &ifr) == -1) 1374 warn("SIOCSIFDESCR"); 1375} 1376 1377void 1378unsetifdesc(const char *noval, int ignored) 1379{ 1380 ifr.ifr_data = (caddr_t)(const char *)""; 1381 if (ioctl(sock, SIOCSIFDESCR, &ifr) == -1) 1382 warn("SIOCSIFDESCR"); 1383} 1384 1385void 1386setifipdst(const char *addr, int ignored) 1387{ 1388 in_getaddr(addr, DSTADDR); 1389 setipdst++; 1390 clearaddr = 0; 1391 newaddr = 0; 1392} 1393#endif 1394 1395#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) 1396void 1397notealias(const char *addr, int param) 1398{ 1399 if (setaddr && doalias == 0 && param < 0) 1400 memcpy(rqtosa(af_ridreq), rqtosa(af_addreq), 1401 rqtosa(af_addreq)->sa_len); 1402 doalias = param; 1403 if (param < 0) { 1404 clearaddr = 1; 1405 newaddr = 0; 1406 } else 1407 clearaddr = 0; 1408} 1409 1410void 1411setifdstaddr(const char *addr, int param) 1412{ 1413 setaddr++; 1414 setipdst++; 1415 afp->af_getaddr(addr, DSTADDR); 1416} 1417 1418/* 1419 * Note: doing an SIOCGIFFLAGS scribbles on the union portion 1420 * of the ifreq structure, which may confuse other parts of ifconfig. 1421 * Make a private copy so we can avoid that. 1422 */ 1423void 1424setifflags(const char *vname, int value) 1425{ 1426 struct ifreq my_ifr; 1427 1428 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 1429 1430 if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)&my_ifr) == -1) 1431 err(1, "%s: SIOCGIFFLAGS", my_ifr.ifr_name); 1432 (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name)); 1433 flags = my_ifr.ifr_flags; 1434 1435 if (value < 0) { 1436 value = -value; 1437 flags &= ~value; 1438 } else 1439 flags |= value; 1440 my_ifr.ifr_flags = flags; 1441 if (ioctl(sock, SIOCSIFFLAGS, (caddr_t)&my_ifr) == -1) 1442 err(1, "%s: SIOCSIFFLAGS", my_ifr.ifr_name); 1443} 1444 1445void 1446setifxflags(const char *vname, int value) 1447{ 1448 struct ifreq my_ifr; 1449 1450 bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); 1451 1452 if (ioctl(sock, SIOCGIFXFLAGS, (caddr_t)&my_ifr) == -1) 1453 warn("%s: SIOCGIFXFLAGS", my_ifr.ifr_name); 1454 (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name)); 1455 xflags = my_ifr.ifr_flags; 1456 1457 if (value < 0) { 1458 value = -value; 1459 xflags &= ~value; 1460 } else 1461 xflags |= value; 1462 my_ifr.ifr_flags = xflags; 1463 if (ioctl(sock, SIOCSIFXFLAGS, (caddr_t)&my_ifr) == -1) 1464 warn("%s: SIOCSIFXFLAGS", my_ifr.ifr_name); 1465} 1466 1467void 1468addaf(const char *vname, int value) 1469{ 1470 struct if_afreq ifar; 1471 1472 strlcpy(ifar.ifar_name, ifname, sizeof(ifar.ifar_name)); 1473 ifar.ifar_af = value; 1474 if (ioctl(sock, SIOCIFAFATTACH, (caddr_t)&ifar) == -1) 1475 warn("%s: SIOCIFAFATTACH", ifar.ifar_name); 1476} 1477 1478void 1479removeaf(const char *vname, int value) 1480{ 1481 struct if_afreq ifar; 1482 1483 strlcpy(ifar.ifar_name, ifname, sizeof(ifar.ifar_name)); 1484 ifar.ifar_af = value; 1485 if (ioctl(sock, SIOCIFAFDETACH, (caddr_t)&ifar) == -1) 1486 warn("%s: SIOCIFAFDETACH", ifar.ifar_name); 1487} 1488 1489void 1490setia6flags(const char *vname, int value) 1491{ 1492 1493 if (value < 0) { 1494 value = -value; 1495 in6_addreq.ifra_flags &= ~value; 1496 } else 1497 in6_addreq.ifra_flags |= value; 1498} 1499 1500void 1501setia6pltime(const char *val, int d) 1502{ 1503 1504 setia6lifetime("pltime", val); 1505} 1506 1507void 1508setia6vltime(const char *val, int d) 1509{ 1510 1511 setia6lifetime("vltime", val); 1512} 1513 1514void 1515setia6lifetime(const char *cmd, const char *val) 1516{ 1517 const char *errmsg = NULL; 1518 time_t newval, t; 1519 1520 newval = strtonum(val, 0, 1000000, &errmsg); 1521 if (errmsg) 1522 errx(1, "invalid %s %s: %s", cmd, val, errmsg); 1523 1524 t = time(NULL); 1525 1526 if (afp->af_af != AF_INET6) 1527 errx(1, "%s not allowed for this address family", cmd); 1528 if (strcmp(cmd, "vltime") == 0) { 1529 in6_addreq.ifra_lifetime.ia6t_expire = t + newval; 1530 in6_addreq.ifra_lifetime.ia6t_vltime = newval; 1531 } else if (strcmp(cmd, "pltime") == 0) { 1532 in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; 1533 in6_addreq.ifra_lifetime.ia6t_pltime = newval; 1534 } 1535} 1536 1537void 1538setia6eui64(const char *cmd, int val) 1539{ 1540 struct ifaddrs *ifap, *ifa; 1541 const struct sockaddr_in6 *sin6 = NULL; 1542 const struct in6_addr *lladdr = NULL; 1543 struct in6_addr *in6; 1544 1545 if (afp->af_af != AF_INET6) 1546 errx(1, "%s not allowed for this address family", cmd); 1547 1548 addaf(ifname, AF_INET6); 1549 1550 in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr; 1551 if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0) 1552 errx(1, "interface index is already filled"); 1553 if (getifaddrs(&ifap) != 0) 1554 err(1, "getifaddrs"); 1555 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1556 if (ifa->ifa_addr->sa_family == AF_INET6 && 1557 strcmp(ifa->ifa_name, ifname) == 0) { 1558 sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; 1559 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1560 lladdr = &sin6->sin6_addr; 1561 break; 1562 } 1563 } 1564 } 1565 if (!lladdr) 1566 errx(1, "could not determine link local address"); 1567 1568 memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8); 1569 1570 freeifaddrs(ifap); 1571} 1572 1573void 1574setautoconf(const char *cmd, int val) 1575{ 1576 switch (afp->af_af) { 1577 case AF_INET: 1578 setifxflags("inet", val * IFXF_AUTOCONF4); 1579 break; 1580 case AF_INET6: 1581 if (val > 0) 1582 setifxflags("inet6", (IFXF_AUTOCONF6 | 1583 IFXF_AUTOCONF6TEMP)); 1584 else 1585 setifxflags("inet6", -IFXF_AUTOCONF6); 1586 break; 1587 default: 1588 errx(1, "autoconf not allowed for this address family"); 1589 } 1590} 1591 1592void 1593settemporary(const char *cmd, int val) 1594{ 1595 switch (afp->af_af) { 1596 case AF_INET6: 1597 setifxflags("inet6", val * IFXF_AUTOCONF6TEMP); 1598 break; 1599 default: 1600 errx(1, "temporary not allowed for this address family"); 1601 } 1602} 1603 1604#ifndef SMALL 1605void 1606setifmetric(const char *val, int ignored) 1607{ 1608 const char *errmsg = NULL; 1609 1610 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1611 1612 ifr.ifr_metric = strtonum(val, 0, INT_MAX, &errmsg); 1613 if (errmsg) 1614 errx(1, "metric %s: %s", val, errmsg); 1615 if (ioctl(sock, SIOCSIFMETRIC, (caddr_t)&ifr) == -1) 1616 warn("SIOCSIFMETRIC"); 1617} 1618#endif 1619 1620void 1621setifmtu(const char *val, int d) 1622{ 1623 const char *errmsg = NULL; 1624 1625 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1626 1627 ifr.ifr_mtu = strtonum(val, 0, INT_MAX, &errmsg); 1628 if (errmsg) 1629 errx(1, "mtu %s: %s", val, errmsg); 1630 if (ioctl(sock, SIOCSIFMTU, (caddr_t)&ifr) == -1) 1631 warn("SIOCSIFMTU"); 1632} 1633 1634void 1635setifllprio(const char *val, int d) 1636{ 1637 const char *errmsg = NULL; 1638 1639 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1640 1641 ifr.ifr_llprio = strtonum(val, 0, UCHAR_MAX, &errmsg); 1642 if (errmsg) 1643 errx(1, "llprio %s: %s", val, errmsg); 1644 if (ioctl(sock, SIOCSIFLLPRIO, (caddr_t)&ifr) == -1) 1645 warn("SIOCSIFLLPRIO"); 1646} 1647 1648void 1649setifgroup(const char *group_name, int dummy) 1650{ 1651 struct ifgroupreq ifgr; 1652 size_t namelen; 1653 1654 memset(&ifgr, 0, sizeof(ifgr)); 1655 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); 1656 1657 namelen = strlen(group_name); 1658 if (namelen == 0) 1659 errx(1, "setifgroup: group name empty"); 1660 if (namelen >= IFNAMSIZ) 1661 errx(1, "setifgroup: group name too long"); 1662 if (isdigit((unsigned char)group_name[namelen - 1])) 1663 errx(1, "setifgroup: group names may not end in a digit"); 1664 1665 strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ); 1666 if (ioctl(sock, SIOCAIFGROUP, (caddr_t)&ifgr) == -1) { 1667 if (errno != EEXIST) 1668 err(1,"%s: SIOCAIFGROUP", group_name); 1669 } 1670} 1671 1672void 1673unsetifgroup(const char *group_name, int dummy) 1674{ 1675 struct ifgroupreq ifgr; 1676 1677 memset(&ifgr, 0, sizeof(ifgr)); 1678 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); 1679 1680 if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ) 1681 errx(1, "unsetifgroup: group name too long"); 1682 if (ioctl(sock, SIOCDIFGROUP, (caddr_t)&ifgr) == -1) 1683 err(1, "%s: SIOCDIFGROUP", group_name); 1684} 1685 1686const char * 1687get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) 1688{ 1689 int len = *lenp, hexstr; 1690 u_int8_t *p = buf; 1691 1692 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); 1693 if (hexstr) 1694 val += 2; 1695 for (;;) { 1696 if (*val == '\0') 1697 break; 1698 if (sep != NULL && strchr(sep, *val) != NULL) { 1699 val++; 1700 break; 1701 } 1702 if (hexstr) { 1703 if (!isxdigit((u_char)val[0]) || 1704 !isxdigit((u_char)val[1])) { 1705 warnx("bad hexadecimal digits"); 1706 return NULL; 1707 } 1708 } 1709 if (p > buf + len) { 1710 if (hexstr) 1711 warnx("hexadecimal digits too long"); 1712 else 1713 warnx("strings too long"); 1714 return NULL; 1715 } 1716 if (hexstr) { 1717#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) 1718 *p++ = (tohex((u_char)val[0]) << 4) | 1719 tohex((u_char)val[1]); 1720#undef tohex 1721 val += 2; 1722 } else { 1723 if (*val == '\\' && 1724 sep != NULL && strchr(sep, *(val + 1)) != NULL) 1725 val++; 1726 *p++ = *val++; 1727 } 1728 } 1729 len = p - buf; 1730 if (len < *lenp) 1731 memset(p, 0, *lenp - len); 1732 *lenp = len; 1733 return val; 1734} 1735 1736int 1737len_string(const u_int8_t *buf, int len) 1738{ 1739 int i = 0, hasspc = 0; 1740 1741 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { 1742 for (; i < len; i++) { 1743 /* Only print 7-bit ASCII keys */ 1744 if (buf[i] & 0x80 || !isprint(buf[i])) 1745 break; 1746 if (isspace(buf[i])) 1747 hasspc++; 1748 } 1749 } 1750 if (i == len) { 1751 if (hasspc || len == 0) 1752 return len + 2; 1753 else 1754 return len; 1755 } else 1756 return (len * 2) + 2; 1757} 1758 1759int 1760print_string(const u_int8_t *buf, int len) 1761{ 1762 int i = 0, hasspc = 0; 1763 1764 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { 1765 for (; i < len; i++) { 1766 /* Only print 7-bit ASCII keys */ 1767 if (buf[i] & 0x80 || !isprint(buf[i])) 1768 break; 1769 if (isspace(buf[i])) 1770 hasspc++; 1771 } 1772 } 1773 if (i == len) { 1774 if (hasspc || len == 0) { 1775 printf("\"%.*s\"", len, buf); 1776 return len + 2; 1777 } else { 1778 printf("%.*s", len, buf); 1779 return len; 1780 } 1781 } else { 1782 printf("0x"); 1783 for (i = 0; i < len; i++) 1784 printf("%02x", buf[i]); 1785 return (len * 2) + 2; 1786 } 1787} 1788 1789void 1790setifnwid(const char *val, int d) 1791{ 1792 struct ieee80211_nwid nwid; 1793 int len; 1794 1795 if (joinlen != 0) { 1796 errx(1, "nwid and join may not be used at the same time"); 1797 } 1798 1799 if (nwidlen != 0) { 1800 errx(1, "nwid may not be specified twice"); 1801 } 1802 1803 if (d != 0) { 1804 /* no network id is especially desired */ 1805 memset(&nwid, 0, sizeof(nwid)); 1806 len = 0; 1807 } else { 1808 len = sizeof(nwid.i_nwid); 1809 if (get_string(val, NULL, nwid.i_nwid, &len) == NULL) 1810 return; 1811 } 1812 nwidlen = nwid.i_len = len; 1813 (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1814 memcpy(nwidname, nwid.i_nwid, len); 1815 ifr.ifr_data = (caddr_t)&nwid; 1816 if (ioctl(sock, SIOCS80211NWID, (caddr_t)&ifr) == -1) 1817 warn("SIOCS80211NWID"); 1818} 1819 1820 1821void 1822process_join_commands(void) 1823{ 1824 if (!(actions & A_JOIN)) 1825 return; 1826 1827 ifr.ifr_data = (caddr_t)&join; 1828 if (ioctl(sock, SIOCS80211JOIN, (caddr_t)&ifr) == -1) 1829 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); 1830} 1831 1832void 1833setifjoin(const char *val, int d) 1834{ 1835 int len; 1836 1837 if (nwidlen != 0) { 1838 errx(1, "nwid and join may not be used at the same time"); 1839 } 1840 1841 if (joinlen != 0) { 1842 errx(1, "join may not be specified twice"); 1843 } 1844 1845 if (d != 0) { 1846 /* no network id is especially desired */ 1847 memset(&join, 0, sizeof(join)); 1848 len = 0; 1849 } else { 1850 len = sizeof(join.i_nwid); 1851 if (get_string(val, NULL, join.i_nwid, &len) == NULL) 1852 return; 1853 if (len == 0) 1854 join.i_flags |= IEEE80211_JOIN_ANY; 1855 } 1856 joinlen = join.i_len = len; 1857 (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1858 memcpy(joinname, join.i_nwid, len); 1859 1860 actions |= A_JOIN; 1861} 1862 1863void 1864delifjoin(const char *val, int d) 1865{ 1866 struct ieee80211_join join; 1867 int len; 1868 1869 memset(&join, 0, sizeof(join)); 1870 len = 0; 1871 join.i_flags |= IEEE80211_JOIN_DEL; 1872 1873 if (d == -1) { 1874 ifr.ifr_data = (caddr_t)&join; 1875 if (ioctl(sock, SIOCS80211JOIN, (caddr_t)&ifr) == -1) 1876 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); 1877 } 1878 1879 len = sizeof(join.i_nwid); 1880 if (get_string(val, NULL, join.i_nwid, &len) == NULL) 1881 return; 1882 join.i_len = len; 1883 if (len == 0) 1884 join.i_flags |= IEEE80211_JOIN_ANY; 1885 (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1886 ifr.ifr_data = (caddr_t)&join; 1887 if (ioctl(sock, SIOCS80211JOIN, (caddr_t)&ifr) == -1) 1888 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); 1889} 1890 1891void 1892delifjoinlist(const char *val, int d) 1893{ 1894 struct ieee80211_join join; 1895 1896 memset(&join, 0, sizeof(join)); 1897 join.i_flags |= (IEEE80211_JOIN_DEL | IEEE80211_JOIN_DEL_ALL); 1898 1899 ifr.ifr_data = (caddr_t)&join; 1900 if (ioctl(sock, SIOCS80211JOIN, (caddr_t)&ifr) == -1) 1901 err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); 1902} 1903 1904void 1905setifbssid(const char *val, int d) 1906{ 1907 1908 struct ieee80211_bssid bssid; 1909 struct ether_addr *ea; 1910 1911 if (d != 0) { 1912 /* no BSSID is especially desired */ 1913 memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid)); 1914 } else { 1915 ea = ether_aton((char*)val); 1916 if (ea == NULL) { 1917 warnx("malformed BSSID: %s", val); 1918 return; 1919 } 1920 memcpy(&bssid.i_bssid, ea->ether_addr_octet, 1921 sizeof(bssid.i_bssid)); 1922 } 1923 strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name)); 1924 if (ioctl(sock, SIOCS80211BSSID, &bssid) == -1) 1925 warn("%s: SIOCS80211BSSID", bssid.i_name); 1926} 1927 1928void 1929setifnwkey(const char *val, int d) 1930{ 1931 int i, len; 1932 struct ieee80211_nwkey nwkey; 1933 u_int8_t keybuf[IEEE80211_WEP_NKID][16]; 1934 1935 bzero(&nwkey, sizeof(nwkey)); 1936 bzero(&keybuf, sizeof(keybuf)); 1937 1938 nwkey.i_wepon = IEEE80211_NWKEY_WEP; 1939 nwkey.i_defkid = 1; 1940 if (d == -1) { 1941 /* disable WEP encryption */ 1942 nwkey.i_wepon = IEEE80211_NWKEY_OPEN; 1943 i = 0; 1944 } else if (strcasecmp("persist", val) == 0) { 1945 /* use all values from persistent memory */ 1946 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; 1947 nwkey.i_defkid = 0; 1948 for (i = 0; i < IEEE80211_WEP_NKID; i++) 1949 nwkey.i_key[i].i_keylen = -1; 1950 } else if (strncasecmp("persist:", val, 8) == 0) { 1951 val += 8; 1952 /* program keys in persistent memory */ 1953 nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST; 1954 goto set_nwkey; 1955 } else { 1956 set_nwkey: 1957 if (isdigit((unsigned char)val[0]) && val[1] == ':') { 1958 /* specifying a full set of four keys */ 1959 nwkey.i_defkid = val[0] - '0'; 1960 val += 2; 1961 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1962 len = sizeof(keybuf[i]); 1963 val = get_string(val, ",", keybuf[i], &len); 1964 if (val == NULL) 1965 return; 1966 nwkey.i_key[i].i_keylen = len; 1967 nwkey.i_key[i].i_keydat = keybuf[i]; 1968 } 1969 if (*val != '\0') { 1970 warnx("SIOCS80211NWKEY: too many keys."); 1971 return; 1972 } 1973 } else { 1974 /* 1975 * length of each key must be either a 5 1976 * character ASCII string or 10 hex digits for 1977 * 40 bit encryption, or 13 character ASCII 1978 * string or 26 hex digits for 128 bit 1979 * encryption. 1980 */ 1981 int j; 1982 char *tmp = NULL; 1983 size_t vlen = strlen(val); 1984 switch(vlen) { 1985 case 10: 1986 case 26: 1987 /* 0x must be missing for these lengths */ 1988 j = asprintf(&tmp, "0x%s", val); 1989 if (j == -1) { 1990 warnx("malloc failed"); 1991 return; 1992 } 1993 val = tmp; 1994 break; 1995 case 12: 1996 case 28: 1997 case 5: 1998 case 13: 1999 /* 0xkey or string case - all is ok */ 2000 break; 2001 default: 2002 warnx("Invalid WEP key length"); 2003 return; 2004 } 2005 len = sizeof(keybuf[0]); 2006 val = get_string(val, NULL, keybuf[0], &len); 2007 free(tmp); 2008 if (val == NULL) 2009 return; 2010 nwkey.i_key[0].i_keylen = len; 2011 nwkey.i_key[0].i_keydat = keybuf[0]; 2012 i = 1; 2013 } 2014 } 2015 (void)strlcpy(nwkey.i_name, ifname, sizeof(nwkey.i_name)); 2016 2017 if (actions & A_JOIN) { 2018 memcpy(&join.i_nwkey, &nwkey, sizeof(join.i_nwkey)); 2019 join.i_flags |= IEEE80211_JOIN_NWKEY; 2020 return; 2021 } 2022 2023 if (ioctl(sock, SIOCS80211NWKEY, (caddr_t)&nwkey) == -1) 2024 err(1, "%s: SIOCS80211NWKEY", nwkey.i_name); 2025} 2026 2027void 2028setifwpa(const char *val, int d) 2029{ 2030 struct ieee80211_wpaparams wpa; 2031 2032 memset(&wpa, 0, sizeof(wpa)); 2033 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); 2034 /* Don't read current values. The kernel will set defaults. */ 2035 wpa.i_enabled = d; 2036 2037 if (actions & A_JOIN) { 2038 join.i_wpaparams.i_enabled = d; 2039 join.i_flags |= IEEE80211_JOIN_WPA; 2040 return; 2041 } 2042 2043 if (ioctl(sock, SIOCS80211WPAPARMS, (caddr_t)&wpa) == -1) 2044 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); 2045} 2046 2047void 2048setifwpaprotos(const char *val, int d) 2049{ 2050 struct ieee80211_wpaparams wpa; 2051 char *optlist, *str; 2052 u_int rval = 0; 2053 2054 if ((optlist = strdup(val)) == NULL) 2055 err(1, "strdup"); 2056 str = strtok(optlist, ","); 2057 while (str != NULL) { 2058 if (strcasecmp(str, "wpa1") == 0) 2059 rval |= IEEE80211_WPA_PROTO_WPA1; 2060 else if (strcasecmp(str, "wpa2") == 0) 2061 rval |= IEEE80211_WPA_PROTO_WPA2; 2062 else 2063 errx(1, "wpaprotos: unknown protocol: %s", str); 2064 str = strtok(NULL, ","); 2065 } 2066 free(optlist); 2067 2068 if (actions & A_JOIN) { 2069 join.i_wpaparams.i_protos = rval; 2070 join.i_flags |= IEEE80211_JOIN_WPA; 2071 return; 2072 } 2073 2074 memset(&wpa, 0, sizeof(wpa)); 2075 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); 2076 if (ioctl(sock, SIOCG80211WPAPARMS, (caddr_t)&wpa) == -1) 2077 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); 2078 wpa.i_protos = rval; 2079 /* Let the kernel set up the appropriate default ciphers. */ 2080 wpa.i_ciphers = 0; 2081 wpa.i_groupcipher = 0; 2082 2083 if (ioctl(sock, SIOCS80211WPAPARMS, (caddr_t)&wpa) == -1) 2084 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); 2085} 2086 2087void 2088setifwpaakms(const char *val, int d) 2089{ 2090 struct ieee80211_wpaparams wpa; 2091 char *optlist, *str; 2092 u_int rval = 0; 2093 2094 if ((optlist = strdup(val)) == NULL) 2095 err(1, "strdup"); 2096 str = strtok(optlist, ","); 2097 while (str != NULL) { 2098 if (strcasecmp(str, "psk") == 0) 2099 rval |= IEEE80211_WPA_AKM_PSK; 2100 else if (strcasecmp(str, "802.1x") == 0) 2101 rval |= IEEE80211_WPA_AKM_8021X; 2102 else 2103 errx(1, "wpaakms: unknown akm: %s", str); 2104 str = strtok(NULL, ","); 2105 } 2106 free(optlist); 2107 2108 if (actions & A_JOIN) { 2109 join.i_wpaparams.i_akms = rval; 2110 join.i_wpaparams.i_enabled = 2111 ((rval & IEEE80211_WPA_AKM_8021X) != 0); 2112 join.i_flags |= IEEE80211_JOIN_WPA; 2113 return; 2114 } 2115 2116 memset(&wpa, 0, sizeof(wpa)); 2117 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); 2118 if (ioctl(sock, SIOCG80211WPAPARMS, (caddr_t)&wpa) == -1) 2119 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); 2120 wpa.i_akms = rval; 2121 /* Enable WPA for 802.1x here. PSK case is handled in setifwpakey(). */ 2122 wpa.i_enabled = ((rval & IEEE80211_WPA_AKM_8021X) != 0); 2123 2124 if (ioctl(sock, SIOCS80211WPAPARMS, (caddr_t)&wpa) == -1) 2125 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); 2126} 2127 2128static const struct { 2129 const char *name; 2130 u_int cipher; 2131} ciphers[] = { 2132 { "usegroup", IEEE80211_WPA_CIPHER_USEGROUP }, 2133 { "wep40", IEEE80211_WPA_CIPHER_WEP40 }, 2134 { "tkip", IEEE80211_WPA_CIPHER_TKIP }, 2135 { "ccmp", IEEE80211_WPA_CIPHER_CCMP }, 2136 { "wep104", IEEE80211_WPA_CIPHER_WEP104 } 2137}; 2138 2139u_int 2140getwpacipher(const char *name) 2141{ 2142 int i; 2143 2144 for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) 2145 if (strcasecmp(name, ciphers[i].name) == 0) 2146 return ciphers[i].cipher; 2147 return IEEE80211_WPA_CIPHER_NONE; 2148} 2149 2150void 2151setifwpaciphers(const char *val, int d) 2152{ 2153 struct ieee80211_wpaparams wpa; 2154 char *optlist, *str; 2155 u_int rval = 0; 2156 2157 if ((optlist = strdup(val)) == NULL) 2158 err(1, "strdup"); 2159 str = strtok(optlist, ","); 2160 while (str != NULL) { 2161 u_int cipher = getwpacipher(str); 2162 if (cipher == IEEE80211_WPA_CIPHER_NONE) 2163 errx(1, "wpaciphers: unknown cipher: %s", str); 2164 2165 rval |= cipher; 2166 str = strtok(NULL, ","); 2167 } 2168 free(optlist); 2169 2170 if (actions & A_JOIN) { 2171 join.i_wpaparams.i_ciphers = rval; 2172 join.i_flags |= IEEE80211_JOIN_WPA; 2173 return; 2174 } 2175 2176 memset(&wpa, 0, sizeof(wpa)); 2177 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); 2178 if (ioctl(sock, SIOCG80211WPAPARMS, (caddr_t)&wpa) == -1) 2179 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); 2180 wpa.i_ciphers = rval; 2181 2182 if (ioctl(sock, SIOCS80211WPAPARMS, (caddr_t)&wpa) == -1) 2183 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); 2184} 2185 2186void 2187setifwpagroupcipher(const char *val, int d) 2188{ 2189 struct ieee80211_wpaparams wpa; 2190 u_int cipher; 2191 2192 cipher = getwpacipher(val); 2193 if (cipher == IEEE80211_WPA_CIPHER_NONE) 2194 errx(1, "wpagroupcipher: unknown cipher: %s", val); 2195 2196 memset(&wpa, 0, sizeof(wpa)); 2197 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); 2198 if (ioctl(sock, SIOCG80211WPAPARMS, (caddr_t)&wpa) == -1) 2199 err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); 2200 wpa.i_groupcipher = cipher; 2201 2202 if (actions & A_JOIN) { 2203 join.i_wpaparams.i_groupcipher = cipher; 2204 join.i_flags |= IEEE80211_JOIN_WPA; 2205 return; 2206 } 2207 2208 if (ioctl(sock, SIOCS80211WPAPARMS, (caddr_t)&wpa) == -1) 2209 err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); 2210} 2211 2212void 2213setifwpakey(const char *val, int d) 2214{ 2215 struct ieee80211_wpaparams wpa; 2216 struct ieee80211_wpapsk psk; 2217 struct ieee80211_nwid nwid; 2218 int passlen; 2219 2220 memset(&psk, 0, sizeof(psk)); 2221 if (d != -1) { 2222 memset(&ifr, 0, sizeof(ifr)); 2223 ifr.ifr_data = (caddr_t)&nwid; 2224 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2225 2226 /* Use the value specified in 'join' or 'nwid' */ 2227 if (joinlen != 0) { 2228 memcpy(nwid.i_nwid, joinname, joinlen); 2229 nwid.i_len = joinlen; 2230 } else if (nwidlen != 0) { 2231 memcpy(nwid.i_nwid, nwidname, nwidlen); 2232 nwid.i_len = nwidlen; 2233 } else { 2234 warnx("no nwid or join command, guessing nwid to use"); 2235 2236 if (ioctl(sock, SIOCG80211NWID, (caddr_t)&ifr) == -1) 2237 err(1, "%s: SIOCG80211NWID", ifr.ifr_name); 2238 } 2239 2240 passlen = strlen(val); 2241 if (passlen == 2 + 2 * sizeof(psk.i_psk) && 2242 val[0] == '0' && val[1] == 'x') { 2243 /* Parse a WPA hex key (must be full-length) */ 2244 passlen = sizeof(psk.i_psk); 2245 val = get_string(val, NULL, psk.i_psk, &passlen); 2246 if (val == NULL || passlen != sizeof(psk.i_psk)) 2247 errx(1, "wpakey: invalid pre-shared key"); 2248 } else { 2249 /* Parse a WPA passphrase */ 2250 if (passlen < 8 || passlen > 63) 2251 errx(1, "wpakey: passphrase must be between " 2252 "8 and 63 characters"); 2253 if (nwid.i_len == 0) 2254 errx(1, "wpakey: nwid not set"); 2255 if (pkcs5_pbkdf2(val, passlen, nwid.i_nwid, nwid.i_len, 2256 psk.i_psk, sizeof(psk.i_psk), 4096) != 0) 2257 errx(1, "wpakey: passphrase hashing failed"); 2258 } 2259 psk.i_enabled = 1; 2260 } else 2261 psk.i_enabled = 0; 2262 2263 (void)strlcpy(psk.i_name, ifname, sizeof(psk.i_name)); 2264 2265 if (actions & A_JOIN) { 2266 memcpy(&join.i_wpapsk, &psk, sizeof(join.i_wpapsk)); 2267 join.i_flags |= IEEE80211_JOIN_WPAPSK; 2268 if (!join.i_wpaparams.i_enabled) 2269 setifwpa(NULL, join.i_wpapsk.i_enabled); 2270 return; 2271 } 2272 2273 if (ioctl(sock, SIOCS80211WPAPSK, (caddr_t)&psk) == -1) 2274 err(1, "%s: SIOCS80211WPAPSK", psk.i_name); 2275 2276 /* And ... automatically enable or disable WPA */ 2277 memset(&wpa, 0, sizeof(wpa)); 2278 (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); 2279 if (ioctl(sock, SIOCG80211WPAPARMS, (caddr_t)&wpa) == -1) 2280 err(1, "%s: SIOCG80211WPAPARMS", psk.i_name); 2281 wpa.i_enabled = psk.i_enabled; 2282 if (ioctl(sock, SIOCS80211WPAPARMS, (caddr_t)&wpa) == -1) 2283 err(1, "%s: SIOCS80211WPAPARMS", psk.i_name); 2284} 2285 2286void 2287setifchan(const char *val, int d) 2288{ 2289 struct ieee80211chanreq channel; 2290 const char *errstr; 2291 int chan; 2292 2293 if (val == NULL) { 2294 if (shownet80211chans || shownet80211nodes) 2295 usage(); 2296 shownet80211chans = 1; 2297 return; 2298 } 2299 if (d != 0) 2300 chan = IEEE80211_CHAN_ANY; 2301 else { 2302 chan = strtonum(val, 1, 256, &errstr); 2303 if (errstr) { 2304 warnx("invalid channel %s: %s", val, errstr); 2305 return; 2306 } 2307 } 2308 2309 strlcpy(channel.i_name, ifname, sizeof(channel.i_name)); 2310 channel.i_channel = (u_int16_t)chan; 2311 if (ioctl(sock, SIOCS80211CHANNEL, (caddr_t)&channel) == -1) 2312 warn("%s: SIOCS80211CHANNEL", channel.i_name); 2313} 2314 2315void 2316setifscan(const char *val, int d) 2317{ 2318 if (shownet80211chans || shownet80211nodes) 2319 usage(); 2320 shownet80211nodes = 1; 2321} 2322 2323#ifndef SMALL 2324 2325void 2326setifnwflag(const char *val, int d) 2327{ 2328 static const struct ieee80211_flags nwflags[] = IEEE80211_FLAGS; 2329 u_int i, flag = 0; 2330 2331 for (i = 0; i < (sizeof(nwflags) / sizeof(nwflags[0])); i++) { 2332 if (strcmp(val, nwflags[i].f_name) == 0) { 2333 flag = nwflags[i].f_flag; 2334 break; 2335 } 2336 } 2337 if (flag == 0) 2338 errx(1, "Invalid nwflag: %s", val); 2339 2340 if (ioctl(sock, SIOCG80211FLAGS, (caddr_t)&ifr) != 0) 2341 err(1, "%s: SIOCG80211FLAGS", ifr.ifr_name); 2342 2343 if (d) 2344 ifr.ifr_flags &= ~flag; 2345 else 2346 ifr.ifr_flags |= flag; 2347 2348 if (ioctl(sock, SIOCS80211FLAGS, (caddr_t)&ifr) != 0) 2349 err(1, "%s: SIOCS80211FLAGS", ifr.ifr_name); 2350} 2351 2352void 2353unsetifnwflag(const char *val, int d) 2354{ 2355 setifnwflag(val, 1); 2356} 2357 2358void 2359setifpowersave(const char *val, int d) 2360{ 2361 struct ieee80211_power power; 2362 const char *errmsg = NULL; 2363 2364 (void)strlcpy(power.i_name, ifname, sizeof(power.i_name)); 2365 if (ioctl(sock, SIOCG80211POWER, (caddr_t)&power) == -1) { 2366 warn("%s: SIOCG80211POWER", power.i_name); 2367 return; 2368 } 2369 2370 if (d != -1 && val != NULL) { 2371 power.i_maxsleep = strtonum(val, 0, INT_MAX, &errmsg); 2372 if (errmsg) 2373 errx(1, "powersave %s: %s", val, errmsg); 2374 } 2375 2376 power.i_enabled = d == -1 ? 0 : 1; 2377 if (ioctl(sock, SIOCS80211POWER, (caddr_t)&power) == -1) 2378 warn("%s: SIOCS80211POWER", power.i_name); 2379} 2380#endif 2381 2382void 2383print_cipherset(u_int32_t cipherset) 2384{ 2385 const char *sep = ""; 2386 int i; 2387 2388 if (cipherset == IEEE80211_WPA_CIPHER_NONE) { 2389 printf("none"); 2390 return; 2391 } 2392 for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) { 2393 if (cipherset & ciphers[i].cipher) { 2394 printf("%s%s", sep, ciphers[i].name); 2395 sep = ","; 2396 } 2397 } 2398} 2399 2400static void 2401print_assoc_failures(uint32_t assoc_fail) 2402{ 2403 /* Filter out the most obvious failure cases. */ 2404 assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_ESSID; 2405 if (assoc_fail & IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY) 2406 assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_WPA_PROTO; 2407 assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY; 2408 2409 if (assoc_fail == 0) 2410 return; 2411 2412 printb_status(assoc_fail, IEEE80211_NODEREQ_ASSOCFAIL_BITS); 2413} 2414 2415void 2416ieee80211_status(void) 2417{ 2418 int len, inwid, ijoin, inwkey, ipsk, ichan, ipwr; 2419 int ibssid, iwpa, assocfail = 0; 2420 struct ieee80211_nwid nwid; 2421 struct ieee80211_join join; 2422 struct ieee80211_nwkey nwkey; 2423 struct ieee80211_wpapsk psk; 2424 struct ieee80211_power power; 2425 struct ieee80211chanreq channel; 2426 struct ieee80211_bssid bssid; 2427 struct ieee80211_wpaparams wpa; 2428 struct ieee80211_nodereq nr; 2429 u_int8_t zero_bssid[IEEE80211_ADDR_LEN]; 2430 struct ether_addr ea; 2431 2432 /* get current status via ioctls */ 2433 memset(&ifr, 0, sizeof(ifr)); 2434 ifr.ifr_data = (caddr_t)&nwid; 2435 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2436 inwid = ioctl(sock, SIOCG80211NWID, (caddr_t)&ifr); 2437 2438 ifr.ifr_data = (caddr_t)&join; 2439 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2440 ijoin = ioctl(sock, SIOCG80211JOIN, (caddr_t)&ifr); 2441 2442 memset(&nwkey, 0, sizeof(nwkey)); 2443 strlcpy(nwkey.i_name, ifname, sizeof(nwkey.i_name)); 2444 inwkey = ioctl(sock, SIOCG80211NWKEY, (caddr_t)&nwkey); 2445 2446 memset(&psk, 0, sizeof(psk)); 2447 strlcpy(psk.i_name, ifname, sizeof(psk.i_name)); 2448 ipsk = ioctl(sock, SIOCG80211WPAPSK, (caddr_t)&psk); 2449 2450 memset(&power, 0, sizeof(power)); 2451 strlcpy(power.i_name, ifname, sizeof(power.i_name)); 2452 ipwr = ioctl(sock, SIOCG80211POWER, &power); 2453 2454 memset(&channel, 0, sizeof(channel)); 2455 strlcpy(channel.i_name, ifname, sizeof(channel.i_name)); 2456 ichan = ioctl(sock, SIOCG80211CHANNEL, (caddr_t)&channel); 2457 2458 memset(&bssid, 0, sizeof(bssid)); 2459 strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name)); 2460 ibssid = ioctl(sock, SIOCG80211BSSID, &bssid); 2461 2462 memset(&wpa, 0, sizeof(wpa)); 2463 strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); 2464 iwpa = ioctl(sock, SIOCG80211WPAPARMS, &wpa); 2465 2466 /* check if any ieee80211 option is active */ 2467 if (inwid == 0 || ijoin == 0 || inwkey == 0 || ipsk == 0 || 2468 ipwr == 0 || ichan == 0 || ibssid == 0 || iwpa == 0) 2469 fputs("\tieee80211:", stdout); 2470 else 2471 return; 2472 2473 if (inwid == 0) { 2474 /* nwid.i_nwid is not NUL terminated. */ 2475 len = nwid.i_len; 2476 if (len > IEEE80211_NWID_LEN) 2477 len = IEEE80211_NWID_LEN; 2478 if (ijoin == 0 && join.i_flags & IEEE80211_JOIN_FOUND) 2479 fputs(" join ", stdout); 2480 else 2481 fputs(" nwid ", stdout); 2482 print_string(nwid.i_nwid, len); 2483 } 2484 2485 if (ichan == 0 && channel.i_channel != 0 && 2486 channel.i_channel != IEEE80211_CHAN_ANY) 2487 printf(" chan %u", channel.i_channel); 2488 2489 memset(&zero_bssid, 0, sizeof(zero_bssid)); 2490 if (ibssid == 0 && 2491 memcmp(bssid.i_bssid, zero_bssid, IEEE80211_ADDR_LEN) != 0) { 2492 memcpy(&ea.ether_addr_octet, bssid.i_bssid, 2493 sizeof(ea.ether_addr_octet)); 2494 printf(" bssid %s", ether_ntoa(&ea)); 2495 2496 bzero(&nr, sizeof(nr)); 2497 bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr)); 2498 strlcpy(nr.nr_ifname, ifname, sizeof(nr.nr_ifname)); 2499 if (ioctl(sock, SIOCG80211NODE, &nr) == 0) { 2500 if (nr.nr_max_rssi) 2501 printf(" %u%%", IEEE80211_NODEREQ_RSSI(&nr)); 2502 else 2503 printf(" %ddBm", nr.nr_rssi); 2504 assocfail = nr.nr_assoc_fail; 2505 } 2506 } 2507 2508 if (inwkey == 0 && nwkey.i_wepon > IEEE80211_NWKEY_OPEN) 2509 fputs(" nwkey", stdout); 2510 2511 if (ipsk == 0 && psk.i_enabled) 2512 fputs(" wpakey", stdout); 2513 if (iwpa == 0 && wpa.i_enabled) { 2514 const char *sep; 2515 2516 fputs(" wpaprotos ", stdout); sep = ""; 2517 if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1) { 2518 fputs("wpa1", stdout); 2519 sep = ","; 2520 } 2521 if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) 2522 printf("%swpa2", sep); 2523 2524 fputs(" wpaakms ", stdout); sep = ""; 2525 if (wpa.i_akms & IEEE80211_WPA_AKM_PSK) { 2526 fputs("psk", stdout); 2527 sep = ","; 2528 } 2529 if (wpa.i_akms & IEEE80211_WPA_AKM_8021X) 2530 printf("%s802.1x", sep); 2531 2532 fputs(" wpaciphers ", stdout); 2533 print_cipherset(wpa.i_ciphers); 2534 2535 fputs(" wpagroupcipher ", stdout); 2536 print_cipherset(wpa.i_groupcipher); 2537 } 2538 2539 if (ipwr == 0 && power.i_enabled) 2540 printf(" powersave on (%dms sleep)", power.i_maxsleep); 2541 2542 if (ioctl(sock, SIOCG80211FLAGS, (caddr_t)&ifr) == 0 && 2543 ifr.ifr_flags) { 2544 putchar(' '); 2545 printb_status(ifr.ifr_flags, IEEE80211_F_USERBITS); 2546 } 2547 2548 if (assocfail) { 2549 putchar(' '); 2550 print_assoc_failures(assocfail); 2551 } 2552 putchar('\n'); 2553 if (show_join) 2554 join_status(); 2555 if (shownet80211chans) 2556 ieee80211_listchans(); 2557 else if (shownet80211nodes) 2558 ieee80211_listnodes(); 2559} 2560 2561void 2562showjoin(const char *cmd, int val) 2563{ 2564 show_join = 1; 2565 return; 2566} 2567 2568void 2569join_status(void) 2570{ 2571 struct ieee80211_joinreq_all ja; 2572 struct ieee80211_join *jn = NULL; 2573 struct ieee80211_wpaparams *wpa; 2574 int jsz = 100; 2575 int ojsz; 2576 int i; 2577 int r; 2578 int maxlen, len; 2579 2580 bzero(&ja, sizeof(ja)); 2581 jn = recallocarray(NULL, 0, jsz, sizeof(*jn)); 2582 if (jn == NULL) 2583 err(1, "recallocarray"); 2584 ojsz = jsz; 2585 while (1) { 2586 ja.ja_node = jn; 2587 ja.ja_size = jsz * sizeof(*jn); 2588 strlcpy(ja.ja_ifname, ifname, sizeof(ja.ja_ifname)); 2589 2590 if ((r = ioctl(sock, SIOCG80211JOINALL, &ja)) != 0) { 2591 if (errno == E2BIG) { 2592 jsz += 100; 2593 jn = recallocarray(jn, ojsz, jsz, sizeof(*jn)); 2594 if (jn == NULL) 2595 err(1, "recallocarray"); 2596 ojsz = jsz; 2597 continue; 2598 } else if (errno != ENOENT) 2599 warn("%s: SIOCG80211JOINALL", ja.ja_ifname); 2600 return; 2601 } 2602 break; 2603 } 2604 2605 if (!ja.ja_nodes) 2606 return; 2607 2608 maxlen = 0; 2609 for (i = 0; i < ja.ja_nodes; i++) { 2610 len = len_string(jn[i].i_nwid, jn[i].i_len); 2611 if (len > maxlen) 2612 maxlen = len; 2613 } 2614 2615 for (i = 0; i < ja.ja_nodes; i++) { 2616 printf("\t "); 2617 if (jn[i].i_len > IEEE80211_NWID_LEN) 2618 jn[i].i_len = IEEE80211_NWID_LEN; 2619 len = print_string(jn[i].i_nwid, jn[i].i_len); 2620 printf("%-*s", maxlen - len, ""); 2621 if (jn[i].i_flags) { 2622 const char *sep; 2623 printf(" "); 2624 2625 if (jn[i].i_flags & IEEE80211_JOIN_NWKEY) 2626 printf("nwkey"); 2627 2628 if (jn[i].i_flags & IEEE80211_JOIN_WPA) { 2629 wpa = &jn[i].i_wpaparams; 2630 2631 printf("wpaprotos "); sep = ""; 2632 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1) { 2633 printf("wpa1"); 2634 sep = ","; 2635 } 2636 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2) 2637 printf("%swpa2", sep); 2638 2639 printf(" wpaakms "); sep = ""; 2640 if (wpa->i_akms & IEEE80211_WPA_AKM_PSK) { 2641 printf("psk"); 2642 sep = ","; 2643 } 2644 if (wpa->i_akms & IEEE80211_WPA_AKM_8021X) 2645 printf("%s802.1x", sep); 2646 2647 printf(" wpaciphers "); 2648 print_cipherset(wpa->i_ciphers); 2649 2650 printf(" wpagroupcipher "); 2651 print_cipherset(wpa->i_groupcipher); 2652 } 2653 } 2654 putchar('\n'); 2655 } 2656} 2657 2658void 2659ieee80211_listchans(void) 2660{ 2661 static struct ieee80211_chaninfo chans[256]; 2662 struct ieee80211_chanreq_all ca; 2663 int i; 2664 2665 bzero(&ca, sizeof(ca)); 2666 bzero(chans, sizeof(chans)); 2667 ca.i_chans = chans; 2668 strlcpy(ca.i_name, ifname, sizeof(ca.i_name)); 2669 2670 if (ioctl(sock, SIOCG80211ALLCHANS, &ca) != 0) { 2671 warn("%s: SIOCG80211ALLCHANS", ca.i_name); 2672 return; 2673 } 2674 printf("\t\t%4s %-8s %s\n", "chan", "freq", "properties"); 2675 for (i = 1; i < nitems(chans); i++) { 2676 if (chans[i].ic_freq == 0) 2677 continue; 2678 printf("\t\t%4d %4d MHz ", i, chans[i].ic_freq); 2679 if (chans[i].ic_flags & IEEE80211_CHANINFO_PASSIVE) 2680 printf("passive scan"); 2681 else 2682 putchar('-'); 2683 putchar('\n'); 2684 } 2685} 2686 2687/* 2688 * Returns an integer less than, equal to, or greater than zero if nr1's 2689 * RSSI is respectively greater than, equal to, or less than nr2's RSSI. 2690 */ 2691static int 2692rssicmp(const void *nr1, const void *nr2) 2693{ 2694 const struct ieee80211_nodereq *x = nr1, *y = nr2; 2695 return y->nr_rssi < x->nr_rssi ? -1 : y->nr_rssi > x->nr_rssi; 2696} 2697 2698void 2699ieee80211_listnodes(void) 2700{ 2701 struct ieee80211_nodereq_all na; 2702 struct ieee80211_nodereq nr[512]; 2703 struct ifreq ifr; 2704 int i; 2705 2706 if ((flags & IFF_UP) == 0) { 2707 printf("\t\tcannot scan, interface is down\n"); 2708 return; 2709 } 2710 2711 bzero(&ifr, sizeof(ifr)); 2712 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2713 2714 if (ioctl(sock, SIOCS80211SCAN, (caddr_t)&ifr) != 0) { 2715 if (errno == EPERM) 2716 printf("\t\tno permission to scan\n"); 2717 return; 2718 } 2719 2720 bzero(&na, sizeof(na)); 2721 bzero(&nr, sizeof(nr)); 2722 na.na_node = nr; 2723 na.na_size = sizeof(nr); 2724 strlcpy(na.na_ifname, ifname, sizeof(na.na_ifname)); 2725 2726 if (ioctl(sock, SIOCG80211ALLNODES, &na) != 0) { 2727 warn("%s: SIOCG80211ALLNODES", na.na_ifname); 2728 return; 2729 } 2730 2731 if (!na.na_nodes) 2732 printf("\t\tnone\n"); 2733 else 2734 qsort(nr, na.na_nodes, sizeof(*nr), rssicmp); 2735 2736 for (i = 0; i < na.na_nodes; i++) { 2737 printf("\t\t"); 2738 ieee80211_printnode(&nr[i]); 2739 putchar('\n'); 2740 } 2741} 2742 2743void 2744ieee80211_printnode(struct ieee80211_nodereq *nr) 2745{ 2746 int len, i; 2747 2748 if (nr->nr_flags & IEEE80211_NODEREQ_AP || 2749 nr->nr_capinfo & IEEE80211_CAPINFO_IBSS) { 2750 len = nr->nr_nwid_len; 2751 if (len > IEEE80211_NWID_LEN) 2752 len = IEEE80211_NWID_LEN; 2753 printf("nwid "); 2754 print_string(nr->nr_nwid, len); 2755 putchar(' '); 2756 2757 printf("chan %u ", nr->nr_channel); 2758 2759 printf("bssid %s ", 2760 ether_ntoa((struct ether_addr*)nr->nr_bssid)); 2761 } 2762 2763 if ((nr->nr_flags & IEEE80211_NODEREQ_AP) == 0) 2764 printf("lladdr %s ", 2765 ether_ntoa((struct ether_addr*)nr->nr_macaddr)); 2766 2767 if (nr->nr_max_rssi) 2768 printf("%u%% ", IEEE80211_NODEREQ_RSSI(nr)); 2769 else 2770 printf("%ddBm ", nr->nr_rssi); 2771 2772 if (nr->nr_pwrsave) 2773 printf("powersave "); 2774 /* 2775 * Print our current Tx rate for associated nodes. 2776 * Print the fastest supported rate for APs. 2777 */ 2778 if ((nr->nr_flags & (IEEE80211_NODEREQ_AP)) == 0) { 2779 if (nr->nr_flags & IEEE80211_NODEREQ_VHT) { 2780 printf("VHT-MCS%d/%dSS", nr->nr_txmcs, nr->nr_vht_ss); 2781 } else if (nr->nr_flags & IEEE80211_NODEREQ_HT) { 2782 printf("HT-MCS%d ", nr->nr_txmcs); 2783 } else if (nr->nr_nrates) { 2784 printf("%uM ", 2785 (nr->nr_rates[nr->nr_txrate] & IEEE80211_RATE_VAL) 2786 / 2); 2787 } 2788 } else if (nr->nr_max_rxrate) { 2789 printf("%uM HT ", nr->nr_max_rxrate); 2790 } else if (nr->nr_rxmcs[0] != 0) { 2791 for (i = IEEE80211_HT_NUM_MCS - 1; i >= 0; i--) { 2792 if (nr->nr_rxmcs[i / 8] & (1 << (i / 10))) 2793 break; 2794 } 2795 printf("HT-MCS%d ", i); 2796 } else if (nr->nr_nrates) { 2797 printf("%uM ", 2798 (nr->nr_rates[nr->nr_nrates - 1] & IEEE80211_RATE_VAL) / 2); 2799 } 2800 /* ESS is the default, skip it */ 2801 nr->nr_capinfo &= ~IEEE80211_CAPINFO_ESS; 2802 if (nr->nr_capinfo) { 2803 printb_status(nr->nr_capinfo, IEEE80211_CAPINFO_BITS); 2804 if (nr->nr_capinfo & IEEE80211_CAPINFO_PRIVACY) { 2805 if (nr->nr_rsnprotos) { 2806 if (nr->nr_rsnprotos & IEEE80211_WPA_PROTO_WPA2) 2807 fputs(",wpa2", stdout); 2808 if (nr->nr_rsnprotos & IEEE80211_WPA_PROTO_WPA1) 2809 fputs(",wpa1", stdout); 2810 } else 2811 fputs(",wep", stdout); 2812 2813 if (nr->nr_rsnakms & IEEE80211_WPA_AKM_8021X || 2814 nr->nr_rsnakms & IEEE80211_WPA_AKM_SHA256_8021X) 2815 fputs(",802.1x", stdout); 2816 } 2817 putchar(' '); 2818 } 2819 2820 if ((nr->nr_flags & IEEE80211_NODEREQ_AP) == 0) 2821 printb_status(IEEE80211_NODEREQ_STATE(nr->nr_state), 2822 IEEE80211_NODEREQ_STATE_BITS); 2823 else if (nr->nr_assoc_fail) 2824 print_assoc_failures(nr->nr_assoc_fail); 2825} 2826 2827void 2828init_current_media(void) 2829{ 2830 struct ifmediareq ifmr; 2831 2832 /* 2833 * If we have not yet done so, grab the currently-selected 2834 * media. 2835 */ 2836 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { 2837 (void) memset(&ifmr, 0, sizeof(ifmr)); 2838 (void) strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 2839 2840 if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) { 2841 /* 2842 * If we get E2BIG, the kernel is telling us 2843 * that there are more, so we can ignore it. 2844 */ 2845 if (errno != E2BIG) 2846 err(1, "%s: SIOCGIFMEDIA", ifmr.ifm_name); 2847 } 2848 2849 media_current = ifmr.ifm_current; 2850 } 2851 2852 /* Sanity. */ 2853 if (IFM_TYPE(media_current) == 0) 2854 errx(1, "%s: no link type?", ifname); 2855} 2856 2857void 2858process_media_commands(void) 2859{ 2860 2861 if ((actions & (A_MEDIA|A_MEDIAOPT|A_MEDIAMODE)) == 0) { 2862 /* Nothing to do. */ 2863 return; 2864 } 2865 2866 /* 2867 * Media already set up, and commands sanity-checked. Set/clear 2868 * any options, and we're ready to go. 2869 */ 2870 media_current |= mediaopt_set; 2871 media_current &= ~mediaopt_clear; 2872 2873 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 2874 ifr.ifr_media = media_current; 2875 2876 if (ioctl(sock, SIOCSIFMEDIA, (caddr_t)&ifr) == -1) 2877 err(1, "%s: SIOCSIFMEDIA", ifr.ifr_name); 2878} 2879 2880void 2881setmedia(const char *val, int d) 2882{ 2883 uint64_t type, subtype, inst; 2884 2885 if (val == NULL) { 2886 if (showmediaflag) 2887 usage(); 2888 showmediaflag = 1; 2889 return; 2890 } 2891 2892 init_current_media(); 2893 2894 /* Only one media command may be given. */ 2895 if (actions & A_MEDIA) 2896 errx(1, "only one `media' command may be issued"); 2897 2898 /* Must not come after mode commands */ 2899 if (actions & A_MEDIAMODE) 2900 errx(1, "may not issue `media' after `mode' commands"); 2901 2902 /* Must not come after mediaopt commands */ 2903 if (actions & A_MEDIAOPT) 2904 errx(1, "may not issue `media' after `mediaopt' commands"); 2905 2906 /* 2907 * No need to check if `instance' has been issued; setmediainst() 2908 * craps out if `media' has not been specified. 2909 */ 2910 2911 type = IFM_TYPE(media_current); 2912 inst = IFM_INST(media_current); 2913 2914 /* Look up the subtype. */ 2915 subtype = get_media_subtype(type, val); 2916 2917 /* Build the new current media word. */ 2918 media_current = IFM_MAKEWORD(type, subtype, 0, inst); 2919 2920 /* Media will be set after other processing is complete. */ 2921} 2922 2923void 2924setmediamode(const char *val, int d) 2925{ 2926 uint64_t type, subtype, options, inst, mode; 2927 2928 init_current_media(); 2929 2930 /* Can only issue `mode' once. */ 2931 if (actions & A_MEDIAMODE) 2932 errx(1, "only one `mode' command may be issued"); 2933 2934 type = IFM_TYPE(media_current); 2935 subtype = IFM_SUBTYPE(media_current); 2936 options = IFM_OPTIONS(media_current); 2937 inst = IFM_INST(media_current); 2938 2939 if ((mode = get_media_mode(type, val)) == -1) 2940 errx(1, "invalid media mode: %s", val); 2941 media_current = IFM_MAKEWORD(type, subtype, options, inst) | mode; 2942 /* Media will be set after other processing is complete. */ 2943} 2944 2945void 2946unsetmediamode(const char *val, int d) 2947{ 2948 uint64_t type, subtype, options, inst; 2949 2950 init_current_media(); 2951 2952 /* Can only issue `mode' once. */ 2953 if (actions & A_MEDIAMODE) 2954 errx(1, "only one `mode' command may be issued"); 2955 2956 type = IFM_TYPE(media_current); 2957 subtype = IFM_SUBTYPE(media_current); 2958 options = IFM_OPTIONS(media_current); 2959 inst = IFM_INST(media_current); 2960 2961 media_current = IFM_MAKEWORD(type, subtype, options, inst) | 2962 (IFM_AUTO << IFM_MSHIFT); 2963 /* Media will be set after other processing is complete. */ 2964} 2965 2966void 2967setmediaopt(const char *val, int d) 2968{ 2969 2970 init_current_media(); 2971 2972 /* Can only issue `mediaopt' once. */ 2973 if (actions & A_MEDIAOPTSET) 2974 errx(1, "only one `mediaopt' command may be issued"); 2975 2976 /* Can't issue `mediaopt' if `instance' has already been issued. */ 2977 if (actions & A_MEDIAINST) 2978 errx(1, "may not issue `mediaopt' after `instance'"); 2979 2980 mediaopt_set = get_media_options(IFM_TYPE(media_current), val); 2981 2982 /* Media will be set after other processing is complete. */ 2983} 2984 2985void 2986unsetmediaopt(const char *val, int d) 2987{ 2988 2989 init_current_media(); 2990 2991 /* Can only issue `-mediaopt' once. */ 2992 if (actions & A_MEDIAOPTCLR) 2993 errx(1, "only one `-mediaopt' command may be issued"); 2994 2995 /* May not issue `media' and `-mediaopt'. */ 2996 if (actions & A_MEDIA) 2997 errx(1, "may not issue both `media' and `-mediaopt'"); 2998 2999 /* 3000 * No need to check for A_MEDIAINST, since the test for A_MEDIA 3001 * implicitly checks for A_MEDIAINST. 3002 */ 3003 3004 mediaopt_clear = get_media_options(IFM_TYPE(media_current), val); 3005 3006 /* Media will be set after other processing is complete. */ 3007} 3008 3009void 3010setmediainst(const char *val, int d) 3011{ 3012 uint64_t type, subtype, options, inst; 3013 const char *errmsg = NULL; 3014 3015 init_current_media(); 3016 3017 /* Can only issue `instance' once. */ 3018 if (actions & A_MEDIAINST) 3019 errx(1, "only one `instance' command may be issued"); 3020 3021 /* Must have already specified `media' */ 3022 if ((actions & A_MEDIA) == 0) 3023 errx(1, "must specify `media' before `instance'"); 3024 3025 type = IFM_TYPE(media_current); 3026 subtype = IFM_SUBTYPE(media_current); 3027 options = IFM_OPTIONS(media_current); 3028 3029 inst = strtonum(val, 0, IFM_INST_MAX, &errmsg); 3030 if (errmsg) 3031 errx(1, "media instance %s: %s", val, errmsg); 3032 3033 media_current = IFM_MAKEWORD(type, subtype, options, inst); 3034 3035 /* Media will be set after other processing is complete. */ 3036} 3037 3038 3039const struct ifmedia_description ifm_type_descriptions[] = 3040 IFM_TYPE_DESCRIPTIONS; 3041 3042const struct ifmedia_description ifm_subtype_descriptions[] = 3043 IFM_SUBTYPE_DESCRIPTIONS; 3044 3045const struct ifmedia_description ifm_mode_descriptions[] = 3046 IFM_MODE_DESCRIPTIONS; 3047 3048const struct ifmedia_description ifm_option_descriptions[] = 3049 IFM_OPTION_DESCRIPTIONS; 3050 3051const char * 3052get_media_type_string(uint64_t mword) 3053{ 3054 const struct ifmedia_description *desc; 3055 3056 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; 3057 desc++) { 3058 if (IFM_TYPE(mword) == desc->ifmt_word) 3059 return (desc->ifmt_string); 3060 } 3061 return ("<unknown type>"); 3062} 3063 3064const char * 3065get_media_subtype_string(uint64_t mword) 3066{ 3067 const struct ifmedia_description *desc; 3068 3069 for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL; 3070 desc++) { 3071 if (IFM_TYPE_MATCH(desc->ifmt_word, mword) && 3072 IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(mword)) 3073 return (desc->ifmt_string); 3074 } 3075 return ("<unknown subtype>"); 3076} 3077 3078uint64_t 3079get_media_subtype(uint64_t type, const char *val) 3080{ 3081 uint64_t rval; 3082 3083 rval = lookup_media_word(ifm_subtype_descriptions, type, val); 3084 if (rval == -1) 3085 errx(1, "unknown %s media subtype: %s", 3086 get_media_type_string(type), val); 3087 3088 return (rval); 3089} 3090 3091uint64_t 3092get_media_mode(uint64_t type, const char *val) 3093{ 3094 uint64_t rval; 3095 3096 rval = lookup_media_word(ifm_mode_descriptions, type, val); 3097 if (rval == -1) 3098 errx(1, "unknown %s media mode: %s", 3099 get_media_type_string(type), val); 3100 return (rval); 3101} 3102 3103uint64_t 3104get_media_options(uint64_t type, const char *val) 3105{ 3106 char *optlist, *str; 3107 uint64_t option, rval = 0; 3108 3109 /* We muck with the string, so copy it. */ 3110 optlist = strdup(val); 3111 if (optlist == NULL) 3112 err(1, "strdup"); 3113 str = optlist; 3114 3115 /* 3116 * Look up the options in the user-provided comma-separated list. 3117 */ 3118 for (; (str = strtok(str, ",")) != NULL; str = NULL) { 3119 option = lookup_media_word(ifm_option_descriptions, type, str); 3120 if (option == -1) 3121 errx(1, "unknown %s media option: %s", 3122 get_media_type_string(type), str); 3123 rval |= IFM_OPTIONS(option); 3124 } 3125 3126 free(optlist); 3127 return (rval); 3128} 3129 3130uint64_t 3131lookup_media_word(const struct ifmedia_description *desc, uint64_t type, 3132 const char *val) 3133{ 3134 3135 for (; desc->ifmt_string != NULL; desc++) { 3136 if (IFM_TYPE_MATCH(desc->ifmt_word, type) && 3137 strcasecmp(desc->ifmt_string, val) == 0) 3138 return (desc->ifmt_word); 3139 } 3140 return (-1); 3141} 3142 3143void 3144print_media_word(uint64_t ifmw, int print_type, int as_syntax) 3145{ 3146 const struct ifmedia_description *desc; 3147 uint64_t seen_option = 0; 3148 3149 if (print_type) 3150 printf("%s ", get_media_type_string(ifmw)); 3151 printf("%s%s", as_syntax ? "media " : "", 3152 get_media_subtype_string(ifmw)); 3153 3154 /* Find mode. */ 3155 if (IFM_MODE(ifmw) != 0) { 3156 for (desc = ifm_mode_descriptions; desc->ifmt_string != NULL; 3157 desc++) { 3158 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) && 3159 IFM_MODE(ifmw) == IFM_MODE(desc->ifmt_word)) { 3160 printf(" mode %s", desc->ifmt_string); 3161 break; 3162 } 3163 } 3164 } 3165 3166 /* Find options. */ 3167 for (desc = ifm_option_descriptions; desc->ifmt_string != NULL; 3168 desc++) { 3169 if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw) && 3170 (IFM_OPTIONS(ifmw) & IFM_OPTIONS(desc->ifmt_word)) != 0 && 3171 (seen_option & IFM_OPTIONS(desc->ifmt_word)) == 0) { 3172 if (seen_option == 0) 3173 printf(" %s", as_syntax ? "mediaopt " : ""); 3174 printf("%s%s", seen_option ? "," : "", 3175 desc->ifmt_string); 3176 seen_option |= IFM_OPTIONS(desc->ifmt_word); 3177 } 3178 } 3179 if (IFM_INST(ifmw) != 0) 3180 printf(" instance %lld", IFM_INST(ifmw)); 3181} 3182 3183static void 3184print_tunnel(const struct if_laddrreq *req) 3185{ 3186 char psrcaddr[NI_MAXHOST]; 3187 char psrcport[NI_MAXSERV]; 3188 char pdstaddr[NI_MAXHOST]; 3189 char pdstport[NI_MAXSERV]; 3190 const char *ver = ""; 3191 const int niflag = NI_NUMERICHOST | NI_NUMERICSERV | NI_DGRAM; 3192 3193 if (req == NULL) { 3194 printf("(unset)"); 3195 return; 3196 } 3197 3198 psrcaddr[0] = pdstaddr[0] = '\0'; 3199 3200 if (getnameinfo((struct sockaddr *)&req->addr, req->addr.ss_len, 3201 psrcaddr, sizeof(psrcaddr), psrcport, sizeof(psrcport), 3202 niflag) != 0) 3203 strlcpy(psrcaddr, "<error>", sizeof(psrcaddr)); 3204 if (req->addr.ss_family == AF_INET6) 3205 ver = "6"; 3206 3207 printf("inet%s %s", ver, psrcaddr); 3208 if (strcmp(psrcport, "0") != 0) 3209 printf(":%s", psrcport); 3210 3211 if (req->dstaddr.ss_family != AF_UNSPEC) { 3212 in_port_t dstport = 0; 3213 const struct sockaddr_in *sin; 3214 const struct sockaddr_in6 *sin6; 3215 3216 if (getnameinfo((struct sockaddr *)&req->dstaddr, 3217 req->dstaddr.ss_len, pdstaddr, sizeof(pdstaddr), 3218 pdstport, sizeof(pdstport), niflag) != 0) 3219 strlcpy(pdstaddr, "<error>", sizeof(pdstaddr)); 3220 3221 printf(" --> %s", pdstaddr); 3222 if (strcmp(pdstport, "0") != 0) 3223 printf(":%s", pdstport); 3224 } 3225} 3226 3227static void 3228phys_status(int force) 3229{ 3230 struct if_laddrreq req; 3231 struct if_laddrreq *r = &req; 3232 3233 memset(&req, 0, sizeof(req)); 3234 (void) strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)); 3235 if (ioctl(sock, SIOCGLIFPHYADDR, (caddr_t)&req) == -1) { 3236 if (errno != EADDRNOTAVAIL) 3237 return; 3238 3239 r = NULL; 3240 } 3241 3242 printf("\ttunnel: "); 3243 print_tunnel(r); 3244 3245 if (ioctl(sock, SIOCGLIFPHYTTL, (caddr_t)&ifr) == 0) { 3246 if (ifr.ifr_ttl == -1) 3247 printf(" ttl copy"); 3248 else if (ifr.ifr_ttl > 0) 3249 printf(" ttl %d", ifr.ifr_ttl); 3250 } 3251 3252 if (ioctl(sock, SIOCGLIFPHYDF, (caddr_t)&ifr) == 0) 3253 printf(" %s", ifr.ifr_df ? "df" : "nodf"); 3254 3255#ifndef SMALL 3256 if (ioctl(sock, SIOCGLIFPHYECN, (caddr_t)&ifr) == 0) 3257 printf(" %s", ifr.ifr_metric ? "ecn" : "noecn"); 3258 3259 if (ioctl(sock, SIOCGLIFPHYRTABLE, (caddr_t)&ifr) == 0 && 3260 (rdomainid != 0 || ifr.ifr_rdomainid != 0)) 3261 printf(" rdomain %d", ifr.ifr_rdomainid); 3262#endif 3263 printf("\n"); 3264} 3265 3266#ifndef SMALL 3267const uint64_t ifm_status_valid_list[] = IFM_STATUS_VALID_LIST; 3268 3269const struct ifmedia_status_description ifm_status_descriptions[] = 3270 IFM_STATUS_DESCRIPTIONS; 3271#endif 3272 3273const struct if_status_description if_status_descriptions[] = 3274 LINK_STATE_DESCRIPTIONS; 3275 3276const char * 3277get_linkstate(int mt, int link_state) 3278{ 3279 const struct if_status_description *p; 3280 static char buf[8]; 3281 3282 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 3283 if (LINK_STATE_DESC_MATCH(p, mt, link_state)) 3284 return (p->ifs_string); 3285 } 3286 snprintf(buf, sizeof(buf), "[#%d]", link_state); 3287 return buf; 3288} 3289 3290/* 3291 * Print the status of the interface. If an address family was 3292 * specified, show it and it only; otherwise, show them all. 3293 */ 3294void 3295status(int link, struct sockaddr_dl *sdl, int ls, int ifaliases) 3296{ 3297 const struct afswtch *p = afp; 3298 struct ifmediareq ifmr; 3299#ifndef SMALL 3300 struct ifreq ifrdesc; 3301 struct ifkalivereq ikardesc; 3302 char ifdescr[IFDESCRSIZE]; 3303 char pifname[IF_NAMESIZE]; 3304#endif 3305 uint64_t *media_list; 3306 int i; 3307 char sep; 3308 3309 3310 printf("%s: ", ifname); 3311 printb("flags", flags | (xflags << 16), IFFBITS); 3312#ifndef SMALL 3313 if (rdomainid) 3314 printf(" rdomain %d", rdomainid); 3315#endif 3316 if (metric) 3317 printf(" metric %lu", metric); 3318 if (mtu) 3319 printf(" mtu %lu", mtu); 3320 putchar('\n'); 3321#ifndef SMALL 3322 if (showcapsflag) 3323 printifhwfeatures(NULL, 1); 3324#endif 3325 if (sdl != NULL && sdl->sdl_alen && 3326 (sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_CARP)) 3327 (void)printf("\tlladdr %s\n", ether_ntoa( 3328 (struct ether_addr *)LLADDR(sdl))); 3329 3330 sep = '\t'; 3331#ifndef SMALL 3332 (void) memset(&ifrdesc, 0, sizeof(ifrdesc)); 3333 (void) strlcpy(ifrdesc.ifr_name, ifname, sizeof(ifrdesc.ifr_name)); 3334 ifrdesc.ifr_data = (caddr_t)&ifdescr; 3335 if (ioctl(sock, SIOCGIFDESCR, &ifrdesc) == 0 && 3336 strlen(ifrdesc.ifr_data)) 3337 printf("\tdescription: %s\n", ifrdesc.ifr_data); 3338 3339 if (sdl != NULL) { 3340 printf("%cindex %u", sep, sdl->sdl_index); 3341 sep = ' '; 3342 } 3343 if (!is_bridge() && ioctl(sock, SIOCGIFPRIORITY, &ifrdesc) == 0) { 3344 printf("%cpriority %d", sep, ifrdesc.ifr_metric); 3345 sep = ' '; 3346 } 3347#endif 3348 printf("%cllprio %d\n", sep, llprio); 3349 3350#ifndef SMALL 3351 (void) memset(&ikardesc, 0, sizeof(ikardesc)); 3352 (void) strlcpy(ikardesc.ikar_name, ifname, sizeof(ikardesc.ikar_name)); 3353 if (ioctl(sock, SIOCGETKALIVE, &ikardesc) == 0 && 3354 (ikardesc.ikar_timeo != 0 || ikardesc.ikar_cnt != 0)) 3355 printf("\tkeepalive: timeout %d count %d\n", 3356 ikardesc.ikar_timeo, ikardesc.ikar_cnt); 3357 if (ioctl(sock, SIOCGIFPAIR, &ifrdesc) == 0 && ifrdesc.ifr_index != 0 && 3358 if_indextoname(ifrdesc.ifr_index, pifname) != NULL) 3359 printf("\tpatch: %s\n", pifname); 3360#endif 3361 getencap(); 3362#ifndef SMALL 3363 carp_status(); 3364 pfsync_status(); 3365 pppoe_status(); 3366 sppp_status(); 3367 mpls_status(); 3368 pflow_status(); 3369 umb_status(); 3370 wg_status(ifaliases); 3371#endif 3372 trunk_status(); 3373 getifgroups(); 3374 3375 (void) memset(&ifmr, 0, sizeof(ifmr)); 3376 (void) strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 3377 3378 if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) { 3379 /* 3380 * Interface doesn't support SIOC{G,S}IFMEDIA. 3381 */ 3382 if (ls != LINK_STATE_UNKNOWN) 3383 printf("\tstatus: %s\n", 3384 get_linkstate(sdl->sdl_type, ls)); 3385 goto proto_status; 3386 } 3387 3388 if (ifmr.ifm_count == 0) { 3389 warnx("%s: no media types?", ifname); 3390 goto proto_status; 3391 } 3392 3393 media_list = calloc(ifmr.ifm_count, sizeof(*media_list)); 3394 if (media_list == NULL) 3395 err(1, "calloc"); 3396 ifmr.ifm_ulist = media_list; 3397 3398 if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) 3399 err(1, "%s: SIOCGIFMEDIA", ifmr.ifm_name); 3400 3401 printf("\tmedia: "); 3402 print_media_word(ifmr.ifm_current, 1, 0); 3403 if (ifmr.ifm_active != ifmr.ifm_current) { 3404 putchar(' '); 3405 putchar('('); 3406 print_media_word(ifmr.ifm_active, 0, 0); 3407 putchar(')'); 3408 } 3409 putchar('\n'); 3410 3411#ifdef SMALL 3412 printf("\tstatus: %s\n", get_linkstate(sdl->sdl_type, ls)); 3413#else 3414 if (ifmr.ifm_status & IFM_AVALID) { 3415 const struct ifmedia_status_description *ifms; 3416 int bitno, found = 0; 3417 3418 printf("\tstatus: "); 3419 for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { 3420 for (ifms = ifm_status_descriptions; 3421 ifms->ifms_valid != 0; ifms++) { 3422 if (ifms->ifms_type != 3423 IFM_TYPE(ifmr.ifm_current) || 3424 ifms->ifms_valid != 3425 ifm_status_valid_list[bitno]) 3426 continue; 3427 printf("%s%s", found ? ", " : "", 3428 IFM_STATUS_DESC(ifms, ifmr.ifm_status)); 3429 found = 1; 3430 3431 /* 3432 * For each valid indicator bit, there's 3433 * only one entry for each media type, so 3434 * terminate the inner loop now. 3435 */ 3436 break; 3437 } 3438 } 3439 3440 if (found == 0) 3441 printf("unknown"); 3442 putchar('\n'); 3443 } 3444 3445 if (showtransceiver) { 3446 if (if_sff_info(0) == -1) 3447 if (!aflag && errno != EPERM && errno != ENOTTY) 3448 warn("%s transceiver", ifname); 3449 } 3450#endif 3451 ieee80211_status(); 3452 3453 if (showmediaflag) { 3454 uint64_t type; 3455 int printed_type = 0; 3456 3457 for (type = IFM_NMIN; type <= IFM_NMAX; type += IFM_NMIN) { 3458 for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { 3459 if (IFM_TYPE(media_list[i]) == type) { 3460 3461 /* 3462 * Don't advertise media with fixed 3463 * data rates for wireless interfaces. 3464 * Normal people don't need these. 3465 */ 3466 if (type == IFM_IEEE80211 && 3467 (media_list[i] & IFM_TMASK) != 3468 IFM_AUTO) 3469 continue; 3470 3471 if (printed_type == 0) { 3472 printf("\tsupported media:\n"); 3473 printed_type = 1; 3474 } 3475 printf("\t\t"); 3476 print_media_word(media_list[i], 0, 1); 3477 printf("\n"); 3478 } 3479 } 3480 } 3481 } 3482 3483 free(media_list); 3484 3485 proto_status: 3486 if (link == 0) { 3487 if ((p = afp) != NULL) { 3488 p->af_status(1); 3489 } else for (p = afs; p->af_name; p++) { 3490 ifr.ifr_addr.sa_family = p->af_af; 3491 p->af_status(0); 3492 } 3493 } 3494 3495 phys_status(0); 3496#ifndef SMALL 3497 bridge_status(); 3498#endif 3499} 3500 3501void 3502in_status(int force) 3503{ 3504 struct sockaddr_in *sin, sin2; 3505 3506 getsock(AF_INET); 3507 if (sock == -1) { 3508 if (errno == EPROTONOSUPPORT) 3509 return; 3510 err(1, "socket"); 3511 } 3512 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3513 sin = (struct sockaddr_in *)&ifr.ifr_addr; 3514 3515 /* 3516 * We keep the interface address and reset it before each 3517 * ioctl() so we can get ifaliases information (as opposed 3518 * to the primary interface netmask/dstaddr/broadaddr, if 3519 * the ifr_addr field is zero). 3520 */ 3521 memcpy(&sin2, &ifr.ifr_addr, sizeof(sin2)); 3522 3523 printf("\tinet %s", inet_ntoa(sin->sin_addr)); 3524 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3525 if (ioctl(sock, SIOCGIFNETMASK, (caddr_t)&ifr) == -1) { 3526 if (errno != EADDRNOTAVAIL) 3527 warn("SIOCGIFNETMASK"); 3528 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 3529 } else 3530 netmask.sin_addr = 3531 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 3532 if (flags & IFF_POINTOPOINT) { 3533 memcpy(&ifr.ifr_addr, &sin2, sizeof(sin2)); 3534 if (ioctl(sock, SIOCGIFDSTADDR, (caddr_t)&ifr) == -1) { 3535 if (errno == EADDRNOTAVAIL) 3536 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 3537 else 3538 warn("SIOCGIFDSTADDR"); 3539 } 3540 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3541 sin = (struct sockaddr_in *)&ifr.ifr_dstaddr; 3542 printf(" --> %s", inet_ntoa(sin->sin_addr)); 3543 } 3544 printf(" netmask 0x%x", ntohl(netmask.sin_addr.s_addr)); 3545 if (flags & IFF_BROADCAST) { 3546 memcpy(&ifr.ifr_addr, &sin2, sizeof(sin2)); 3547 if (ioctl(sock, SIOCGIFBRDADDR, (caddr_t)&ifr) == -1) { 3548 if (errno == EADDRNOTAVAIL) 3549 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 3550 else 3551 warn("SIOCGIFBRDADDR"); 3552 } 3553 (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3554 sin = (struct sockaddr_in *)&ifr.ifr_addr; 3555 if (sin->sin_addr.s_addr != 0) 3556 printf(" broadcast %s", inet_ntoa(sin->sin_addr)); 3557 } 3558 putchar('\n'); 3559} 3560 3561void 3562setifprefixlen(const char *addr, int d) 3563{ 3564 if (afp->af_getprefix) 3565 afp->af_getprefix(addr, MASK); 3566 explicit_prefix = 1; 3567} 3568 3569void 3570in6_fillscopeid(struct sockaddr_in6 *sin6) 3571{ 3572#ifdef __KAME__ 3573 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 3574 sin6->sin6_scope_id == 0) { 3575 sin6->sin6_scope_id = 3576 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 3577 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; 3578 } 3579#endif /* __KAME__ */ 3580} 3581 3582/* XXX not really an alias */ 3583void 3584in6_alias(struct in6_ifreq *creq) 3585{ 3586 struct sockaddr_in6 *sin6; 3587 struct in6_ifreq ifr6; /* shadows file static variable */ 3588 u_int32_t scopeid; 3589 char hbuf[NI_MAXHOST]; 3590 const int niflag = NI_NUMERICHOST; 3591 3592 /* Get the non-alias address for this interface. */ 3593 getsock(AF_INET6); 3594 if (sock == -1) { 3595 if (errno == EPROTONOSUPPORT) 3596 return; 3597 err(1, "socket"); 3598 } 3599 3600 sin6 = (struct sockaddr_in6 *)&creq->ifr_addr; 3601 3602 in6_fillscopeid(sin6); 3603 scopeid = sin6->sin6_scope_id; 3604 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 3605 hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) 3606 strlcpy(hbuf, "", sizeof hbuf); 3607 printf("\tinet6 %s", hbuf); 3608 3609 if (flags & IFF_POINTOPOINT) { 3610 (void) memset(&ifr6, 0, sizeof(ifr6)); 3611 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); 3612 ifr6.ifr_addr = creq->ifr_addr; 3613 if (ioctl(sock, SIOCGIFDSTADDR_IN6, (caddr_t)&ifr6) == -1) { 3614 if (errno != EADDRNOTAVAIL) 3615 warn("SIOCGIFDSTADDR_IN6"); 3616 (void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr)); 3617 ifr6.ifr_addr.sin6_family = AF_INET6; 3618 ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6); 3619 } 3620 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 3621 in6_fillscopeid(sin6); 3622 if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, 3623 hbuf, sizeof(hbuf), NULL, 0, niflag) != 0) 3624 strlcpy(hbuf, "", sizeof hbuf); 3625 printf(" --> %s", hbuf); 3626 } 3627 3628 (void) memset(&ifr6, 0, sizeof(ifr6)); 3629 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); 3630 ifr6.ifr_addr = creq->ifr_addr; 3631 if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) == -1) { 3632 if (errno != EADDRNOTAVAIL) 3633 warn("SIOCGIFNETMASK_IN6"); 3634 } else { 3635 sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr; 3636 printf(" prefixlen %d", prefix(&sin6->sin6_addr, 3637 sizeof(struct in6_addr))); 3638 } 3639 3640 (void) memset(&ifr6, 0, sizeof(ifr6)); 3641 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); 3642 ifr6.ifr_addr = creq->ifr_addr; 3643 if (ioctl(sock, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) == -1) { 3644 if (errno != EADDRNOTAVAIL) 3645 warn("SIOCGIFAFLAG_IN6"); 3646 } else { 3647 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST) 3648 printf(" anycast"); 3649 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) 3650 printf(" tentative"); 3651 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) 3652 printf(" duplicated"); 3653 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED) 3654 printf(" detached"); 3655 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) 3656 printf(" deprecated"); 3657 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF) 3658 printf(" autoconf"); 3659 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY) 3660 printf(" temporary"); 3661 } 3662 3663 if (scopeid) 3664 printf(" scopeid 0x%x", scopeid); 3665 3666 if (Lflag) { 3667 struct in6_addrlifetime *lifetime; 3668 3669 (void) memset(&ifr6, 0, sizeof(ifr6)); 3670 (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); 3671 ifr6.ifr_addr = creq->ifr_addr; 3672 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 3673 if (ioctl(sock, SIOCGIFALIFETIME_IN6, (caddr_t)&ifr6) == -1) { 3674 if (errno != EADDRNOTAVAIL) 3675 warn("SIOCGIFALIFETIME_IN6"); 3676 } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { 3677 time_t t = time(NULL); 3678 3679 printf(" pltime "); 3680 if (lifetime->ia6t_preferred) { 3681 printf("%s", lifetime->ia6t_preferred < t 3682 ? "0" : 3683 sec2str(lifetime->ia6t_preferred - t)); 3684 } else 3685 printf("infty"); 3686 3687 printf(" vltime "); 3688 if (lifetime->ia6t_expire) { 3689 printf("%s", lifetime->ia6t_expire < t 3690 ? "0" 3691 : sec2str(lifetime->ia6t_expire - t)); 3692 } else 3693 printf("infty"); 3694 } 3695 } 3696 3697 printf("\n"); 3698} 3699 3700void 3701in6_status(int force) 3702{ 3703 in6_alias((struct in6_ifreq *)&ifr6); 3704} 3705 3706#ifndef SMALL 3707void 3708settunnel(const char *src, const char *dst) 3709{ 3710 char srcbuf[HOST_NAME_MAX], dstbuf[HOST_NAME_MAX]; 3711 const char *srcport, *dstport; 3712 const char *srcaddr, *dstaddr; 3713 struct addrinfo *srcres, *dstres; 3714 struct addrinfo hints = { 3715 .ai_family = AF_UNSPEC, 3716 .ai_socktype = SOCK_DGRAM, 3717 .ai_protocol = IPPROTO_UDP, 3718 .ai_flags = AI_PASSIVE, 3719 }; 3720 int ecode; 3721 size_t len; 3722 struct if_laddrreq req; 3723 3724 srcport = strchr(src, ':'); 3725 if (srcport == NULL || srcport != strrchr(src, ':')) { 3726 /* no port or IPv6 */ 3727 srcaddr = src; 3728 srcport = NULL; 3729 } else { 3730 len = srcport - src; 3731 if (len >= sizeof(srcbuf)) 3732 errx(1, "src %s bad value", src); 3733 memcpy(srcbuf, src, len); 3734 srcbuf[len] = '\0'; 3735 3736 srcaddr = srcbuf; 3737 srcport++; 3738 } 3739 3740 dstport = strchr(dst, ':'); 3741 if (dstport == NULL || dstport != strrchr(dst, ':')) { 3742 /* no port or IPv6 */ 3743 dstaddr = dst; 3744 dstport = NULL; 3745 } else { 3746 len = dstport - dst; 3747 if (len >= sizeof(dstbuf)) 3748 errx(1, "dst %s bad value", dst); 3749 memcpy(dstbuf, dst, len); 3750 dstbuf[len] = '\0'; 3751 3752 dstaddr = dstbuf; 3753 dstport++; 3754 } 3755 3756 if ((ecode = getaddrinfo(srcaddr, srcport, &hints, &srcres)) != 0) 3757 errx(1, "error in parsing address string: %s", 3758 gai_strerror(ecode)); 3759 3760 hints.ai_flags = 0; 3761 if ((ecode = getaddrinfo(dstaddr, dstport, &hints, &dstres)) != 0) 3762 errx(1, "error in parsing address string: %s", 3763 gai_strerror(ecode)); 3764 3765 if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) 3766 errx(1, 3767 "source and destination address families do not match"); 3768 3769 memset(&req, 0, sizeof(req)); 3770 (void) strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)); 3771 memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); 3772 memcpy(&req.dstaddr, dstres->ai_addr, dstres->ai_addrlen); 3773 if (ioctl(sock, SIOCSLIFPHYADDR, &req) == -1) 3774 warn("SIOCSLIFPHYADDR"); 3775 3776 freeaddrinfo(srcres); 3777 freeaddrinfo(dstres); 3778} 3779 3780void 3781settunneladdr(const char *src, int ignored) 3782{ 3783 char srcbuf[HOST_NAME_MAX]; 3784 const char *srcport; 3785 const char *srcaddr; 3786 struct addrinfo *srcres; 3787 struct addrinfo hints = { 3788 .ai_family = AF_UNSPEC, 3789 .ai_socktype = SOCK_DGRAM, 3790 .ai_protocol = IPPROTO_UDP, 3791 .ai_flags = AI_PASSIVE, 3792 }; 3793 struct if_laddrreq req; 3794 ssize_t len; 3795 int rv; 3796 3797 srcport = strchr(src, ':'); 3798 if (srcport == NULL || srcport != strrchr(src, ':')) { 3799 /* no port or IPv6 */ 3800 srcaddr = src; 3801 srcport = NULL; 3802 } else { 3803 len = srcport - src; 3804 if (len >= sizeof(srcbuf)) 3805 errx(1, "src %s bad value", src); 3806 memcpy(srcbuf, src, len); 3807 srcbuf[len] = '\0'; 3808 3809 srcaddr = srcbuf; 3810 srcport++; 3811 } 3812 3813 rv = getaddrinfo(srcaddr, srcport, &hints, &srcres); 3814 if (rv != 0) 3815 errx(1, "tunneladdr %s: %s", src, gai_strerror(rv)); 3816 3817 memset(&req, 0, sizeof(req)); 3818 len = strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)); 3819 if (len >= sizeof(req.iflr_name)) 3820 errx(1, "%s: Interface name too long", ifname); 3821 3822 memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); 3823 3824 req.dstaddr.ss_len = 2; 3825 req.dstaddr.ss_family = AF_UNSPEC; 3826 3827 if (ioctl(sock, SIOCSLIFPHYADDR, &req) == -1) 3828 warn("tunneladdr %s", src); 3829 3830 freeaddrinfo(srcres); 3831} 3832 3833void 3834deletetunnel(const char *ignored, int alsoignored) 3835{ 3836 if (ioctl(sock, SIOCDIFPHYADDR, &ifr) == -1) 3837 warn("SIOCDIFPHYADDR"); 3838} 3839 3840void 3841settunnelinst(const char *id, int param) 3842{ 3843 const char *errmsg = NULL; 3844 int rdomainid; 3845 3846 rdomainid = strtonum(id, 0, RT_TABLEID_MAX, &errmsg); 3847 if (errmsg) 3848 errx(1, "rdomain %s: %s", id, errmsg); 3849 3850 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3851 ifr.ifr_rdomainid = rdomainid; 3852 if (ioctl(sock, SIOCSLIFPHYRTABLE, (caddr_t)&ifr) == -1) 3853 warn("SIOCSLIFPHYRTABLE"); 3854} 3855 3856void 3857unsettunnelinst(const char *ignored, int alsoignored) 3858{ 3859 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3860 ifr.ifr_rdomainid = 0; 3861 if (ioctl(sock, SIOCSLIFPHYRTABLE, (caddr_t)&ifr) == -1) 3862 warn("SIOCSLIFPHYRTABLE"); 3863} 3864 3865void 3866settunnelttl(const char *id, int param) 3867{ 3868 const char *errmsg = NULL; 3869 int ttl; 3870 3871 if (strcmp(id, "copy") == 0) 3872 ttl = -1; 3873 else { 3874 ttl = strtonum(id, 0, 0xff, &errmsg); 3875 if (errmsg) 3876 errx(1, "tunnelttl %s: %s", id, errmsg); 3877 } 3878 3879 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3880 ifr.ifr_ttl = ttl; 3881 if (ioctl(sock, SIOCSLIFPHYTTL, (caddr_t)&ifr) == -1) 3882 warn("SIOCSLIFPHYTTL"); 3883} 3884 3885void 3886settunneldf(const char *ignored, int alsoignored) 3887{ 3888 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3889 ifr.ifr_df = 1; 3890 if (ioctl(sock, SIOCSLIFPHYDF, (caddr_t)&ifr) == -1) 3891 warn("SIOCSLIFPHYDF"); 3892} 3893 3894void 3895settunnelnodf(const char *ignored, int alsoignored) 3896{ 3897 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3898 ifr.ifr_df = 0; 3899 if (ioctl(sock, SIOCSLIFPHYDF, (caddr_t)&ifr) == -1) 3900 warn("SIOCSLIFPHYDF"); 3901} 3902 3903void 3904settunnelecn(const char *ignored, int alsoignored) 3905{ 3906 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3907 ifr.ifr_metric = 1; 3908 if (ioctl(sock, SIOCSLIFPHYECN, (caddr_t)&ifr) == -1) 3909 warn("SIOCSLIFPHYECN"); 3910} 3911 3912void 3913settunnelnoecn(const char *ignored, int alsoignored) 3914{ 3915 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 3916 ifr.ifr_metric = 0; 3917 if (ioctl(sock, SIOCSLIFPHYECN, (caddr_t)&ifr) == -1) 3918 warn("SIOCSLIFPHYECN"); 3919} 3920 3921void 3922setvnetflowid(const char *ignored, int alsoignored) 3923{ 3924 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 3925 sizeof(ifr.ifr_name)) 3926 errx(1, "vnetflowid: name is too long"); 3927 3928 ifr.ifr_vnetid = 1; 3929 if (ioctl(sock, SIOCSVNETFLOWID, &ifr) == -1) 3930 warn("SIOCSVNETFLOWID"); 3931} 3932 3933void 3934delvnetflowid(const char *ignored, int alsoignored) 3935{ 3936 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 3937 sizeof(ifr.ifr_name)) 3938 errx(1, "vnetflowid: name is too long"); 3939 3940 ifr.ifr_vnetid = 0; 3941 if (ioctl(sock, SIOCSVNETFLOWID, &ifr) == -1) 3942 warn("SIOCSVNETFLOWID"); 3943} 3944 3945static void 3946pwe3_neighbor(void) 3947{ 3948 const char *prefix = "pwe3 remote label"; 3949 struct if_laddrreq req; 3950 char hbuf[NI_MAXHOST]; 3951 struct sockaddr_mpls *smpls; 3952 int error; 3953 3954 memset(&req, 0, sizeof(req)); 3955 if (strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)) >= 3956 sizeof(req.iflr_name)) 3957 errx(1, "pwe3 neighbor: name is too long"); 3958 3959 if (ioctl(sock, SIOCGPWE3NEIGHBOR, &req) == -1) { 3960 if (errno != EADDRNOTAVAIL) 3961 return; 3962 3963 printf(" %s (unset)", prefix); 3964 return; 3965 } 3966 3967 if (req.dstaddr.ss_family != AF_MPLS) { 3968 warnc(EPFNOSUPPORT, "pwe3 neighbor"); 3969 return; 3970 } 3971 smpls = (struct sockaddr_mpls *)&req.dstaddr; 3972 3973 error = getnameinfo((struct sockaddr *)&req.addr, sizeof(req.addr), 3974 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST); 3975 if (error != 0) { 3976 warnx("%s: %s", prefix, gai_strerror(error)); 3977 return; 3978 } 3979 3980 printf(" %s %u on %s", prefix, smpls->smpls_label, hbuf); 3981} 3982 3983static void 3984pwe3_cword(void) 3985{ 3986 struct ifreq req; 3987 3988 memset(&req, 0, sizeof(req)); 3989 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= 3990 sizeof(req.ifr_name)) 3991 errx(1, "pwe3 control word: name is too long"); 3992 3993 if (ioctl(sock, SIOCGPWE3CTRLWORD, &req) == -1) { 3994 return; 3995 } 3996 3997 printf(" %s", req.ifr_pwe3 ? "cw" : "nocw"); 3998} 3999 4000static void 4001pwe3_fword(void) 4002{ 4003 struct ifreq req; 4004 4005 memset(&req, 0, sizeof(req)); 4006 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= 4007 sizeof(req.ifr_name)) 4008 errx(1, "pwe3 control word: name is too long"); 4009 4010 if (ioctl(sock, SIOCGPWE3FAT, &req) == -1) 4011 return; 4012 4013 printf(" %s", req.ifr_pwe3 ? "fat" : "nofat"); 4014} 4015 4016void 4017mpls_status(void) 4018{ 4019 struct shim_hdr shim; 4020 4021 bzero(&shim, sizeof(shim)); 4022 ifr.ifr_data = (caddr_t)&shim; 4023 4024 if (ioctl(sock, SIOCGETLABEL, (caddr_t)&ifr) == -1) { 4025 if (errno != EADDRNOTAVAIL) 4026 return; 4027 4028 printf("\tmpls: label (unset)"); 4029 } else 4030 printf("\tmpls: label %u", shim.shim_label); 4031 4032 pwe3_neighbor(); 4033 pwe3_cword(); 4034 pwe3_fword(); 4035 4036 printf("\n"); 4037} 4038 4039void 4040setmplslabel(const char *val, int d) 4041{ 4042 struct shim_hdr shim; 4043 const char *estr; 4044 4045 bzero(&shim, sizeof(shim)); 4046 ifr.ifr_data = (caddr_t)&shim; 4047 shim.shim_label = strtonum(val, 0, MPLS_LABEL_MAX, &estr); 4048 4049 if (estr) 4050 errx(1, "mpls label %s is %s", val, estr); 4051 if (ioctl(sock, SIOCSETLABEL, (caddr_t)&ifr) == -1) 4052 warn("SIOCSETLABEL"); 4053} 4054 4055void 4056unsetmplslabel(const char *val, int d) 4057{ 4058 struct ifreq req; 4059 4060 memset(&req, 0, sizeof(req)); 4061 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= 4062 sizeof(req.ifr_name)) 4063 errx(1, "interface name is too long"); 4064 4065 if (ioctl(sock, SIOCDELLABEL, (caddr_t)&ifr) == -1) 4066 warn("-mplslabel"); 4067} 4068 4069static void 4070setpwe3(unsigned long cmd, const char *cmdname, int value) 4071{ 4072 struct ifreq req; 4073 4074 memset(&req, 0, sizeof(req)); 4075 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= 4076 sizeof(req.ifr_name)) 4077 errx(1, "interface name is too long"); 4078 4079 req.ifr_pwe3 = value; 4080 4081 if (ioctl(sock, cmd, &req) == -1) 4082 warn("%s", cmdname); 4083} 4084 4085void 4086setpwe3cw(const char *val, int d) 4087{ 4088 setpwe3(SIOCSPWE3CTRLWORD, "pwecw", 1); 4089} 4090 4091void 4092unsetpwe3cw(const char *val, int d) 4093{ 4094 setpwe3(SIOCSPWE3CTRLWORD, "-pwecw", 0); 4095} 4096 4097void 4098setpwe3fat(const char *val, int d) 4099{ 4100 setpwe3(SIOCSPWE3FAT, "pwefat", 1); 4101} 4102 4103void 4104unsetpwe3fat(const char *val, int d) 4105{ 4106 setpwe3(SIOCSPWE3FAT, "-pwefat", 0); 4107} 4108 4109void 4110setpwe3neighbor(const char *label, const char *neighbor) 4111{ 4112 struct if_laddrreq req; 4113 struct addrinfo hints, *res; 4114 struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)&req.dstaddr; 4115 const char *errstr; 4116 int error; 4117 4118 memset(&req, 0, sizeof(req)); 4119 if (strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)) >= 4120 sizeof(req.iflr_name)) 4121 errx(1, "interface name is too long"); 4122 4123 memset(&hints, 0, sizeof(hints)); 4124 hints.ai_family = AF_UNSPEC; 4125 hints.ai_socktype = SOCK_DGRAM; 4126 error = getaddrinfo(neighbor, NULL, &hints, &res); 4127 if (error != 0) 4128 errx(1, "pweneighbor %s: %s", neighbor, gai_strerror(error)); 4129 4130 smpls->smpls_len = sizeof(*smpls); 4131 smpls->smpls_family = AF_MPLS; 4132 smpls->smpls_label = strtonum(label, 4133 (MPLS_LABEL_RESERVED_MAX + 1), MPLS_LABEL_MAX, &errstr); 4134 if (errstr != NULL) 4135 errx(1, "pweneighbor: invalid label: %s", errstr); 4136 4137 4138 if (res->ai_addrlen > sizeof(req.addr)) 4139 errx(1, "pweneighbors: unexpected socklen"); 4140 4141 memcpy(&req.addr, res->ai_addr, res->ai_addrlen); 4142 4143 freeaddrinfo(res); 4144 4145 if (ioctl(sock, SIOCSPWE3NEIGHBOR, &req) == -1) 4146 warn("pweneighbor"); 4147} 4148 4149void 4150unsetpwe3neighbor(const char *val, int d) 4151{ 4152 struct ifreq req; 4153 4154 memset(&req, 0, sizeof(req)); 4155 if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= 4156 sizeof(req.ifr_name)) 4157 errx(1, "interface name is too long"); 4158 4159 if (ioctl(sock, SIOCDPWE3NEIGHBOR, &req) == -1) 4160 warn("-pweneighbor"); 4161} 4162 4163void 4164transceiver(const char *value, int d) 4165{ 4166 showtransceiver = 1; 4167} 4168 4169void 4170transceiverdump(const char *value, int d) 4171{ 4172 if (if_sff_info(1) == -1) 4173 err(1, "%s transceiver", ifname); 4174} 4175#endif /* SMALL */ 4176 4177void 4178getvnetflowid(struct ifencap *ife) 4179{ 4180 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 4181 sizeof(ifr.ifr_name)) 4182 errx(1, "vnetflowid: name is too long"); 4183 4184 if (ioctl(sock, SIOCGVNETFLOWID, &ifr) == -1) 4185 return; 4186 4187 if (ifr.ifr_vnetid) 4188 ife->ife_flags |= IFE_VNETFLOWID; 4189} 4190 4191void 4192setvnetid(const char *id, int param) 4193{ 4194 const char *errmsg = NULL; 4195 int64_t vnetid; 4196 4197 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 4198 4199 if (strcasecmp("any", id) == 0) 4200 vnetid = -1; 4201 else { 4202 vnetid = strtonum(id, 0, INT64_MAX, &errmsg); 4203 if (errmsg) 4204 errx(1, "vnetid %s: %s", id, errmsg); 4205 } 4206 4207 ifr.ifr_vnetid = vnetid; 4208 if (ioctl(sock, SIOCSVNETID, (caddr_t)&ifr) == -1) 4209 warn("SIOCSVNETID"); 4210} 4211 4212void 4213delvnetid(const char *ignored, int alsoignored) 4214{ 4215 if (ioctl(sock, SIOCDVNETID, &ifr) == -1) 4216 warn("SIOCDVNETID"); 4217} 4218 4219void 4220getvnetid(struct ifencap *ife) 4221{ 4222 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 4223 sizeof(ifr.ifr_name)) 4224 errx(1, "vnetid: name is too long"); 4225 4226 if (ioctl(sock, SIOCGVNETID, &ifr) == -1) { 4227 if (errno != EADDRNOTAVAIL) 4228 return; 4229 4230 ife->ife_flags |= IFE_VNETID_NONE; 4231 return; 4232 } 4233 4234 if (ifr.ifr_vnetid < 0) { 4235 ife->ife_flags |= IFE_VNETID_ANY; 4236 return; 4237 } 4238 4239 ife->ife_flags |= IFE_VNETID_SET; 4240 ife->ife_vnetid = ifr.ifr_vnetid; 4241} 4242 4243void 4244setifparent(const char *id, int param) 4245{ 4246 struct if_parent ifp; 4247 4248 if (strlcpy(ifp.ifp_name, ifname, sizeof(ifp.ifp_name)) >= 4249 sizeof(ifp.ifp_name)) 4250 errx(1, "parent: name too long"); 4251 4252 if (strlcpy(ifp.ifp_parent, id, sizeof(ifp.ifp_parent)) >= 4253 sizeof(ifp.ifp_parent)) 4254 errx(1, "parent: parent too long"); 4255 4256 if (ioctl(sock, SIOCSIFPARENT, (caddr_t)&ifp) == -1) 4257 warn("%s: %s: SIOCSIFPARENT", ifp.ifp_name, ifp.ifp_parent); 4258} 4259 4260void 4261delifparent(const char *ignored, int alsoignored) 4262{ 4263 if (ioctl(sock, SIOCDIFPARENT, &ifr) == -1) 4264 warn("SIOCDIFPARENT"); 4265} 4266 4267void 4268getifparent(struct ifencap *ife) 4269{ 4270 struct if_parent ifp; 4271 4272 memset(&ifp, 0, sizeof(ifp)); 4273 if (strlcpy(ifp.ifp_name, ifname, sizeof(ifp.ifp_name)) >= 4274 sizeof(ifp.ifp_name)) 4275 errx(1, "parent: name too long"); 4276 4277 if (ioctl(sock, SIOCGIFPARENT, (caddr_t)&ifp) == -1) { 4278 if (errno != EADDRNOTAVAIL) 4279 return; 4280 4281 ife->ife_flags |= IFE_PARENT_NONE; 4282 } else { 4283 memcpy(ife->ife_parent, ifp.ifp_parent, 4284 sizeof(ife->ife_parent)); 4285 ife->ife_flags |= IFE_PARENT_SET; 4286 } 4287} 4288 4289#ifndef SMALL 4290void 4291gettxprio(struct ifencap *ife) 4292{ 4293 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 4294 sizeof(ifr.ifr_name)) 4295 errx(1, "hdr prio: name is too long"); 4296 4297 if (ioctl(sock, SIOCGTXHPRIO, (caddr_t)&ifr) == -1) 4298 return; 4299 4300 ife->ife_flags |= IFE_TXHPRIO_SET; 4301 ife->ife_txhprio = ifr.ifr_hdrprio; 4302} 4303 4304void 4305settxprio(const char *val, int d) 4306{ 4307 const char *errmsg = NULL; 4308 4309 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 4310 sizeof(ifr.ifr_name)) 4311 errx(1, "tx prio: name is too long"); 4312 4313 if (strcmp(val, "packet") == 0) 4314 ifr.ifr_hdrprio = IF_HDRPRIO_PACKET; 4315 else if (strcmp(val, "payload") == 0) 4316 ifr.ifr_hdrprio = IF_HDRPRIO_PAYLOAD; 4317 else { 4318 ifr.ifr_hdrprio = strtonum(val, 4319 IF_HDRPRIO_MIN, IF_HDRPRIO_MAX, &errmsg); 4320 if (errmsg) 4321 errx(1, "tx prio %s: %s", val, errmsg); 4322 } 4323 4324 if (ioctl(sock, SIOCSTXHPRIO, (caddr_t)&ifr) == -1) 4325 warn("SIOCSTXHPRIO"); 4326} 4327 4328void 4329getrxprio(struct ifencap *ife) 4330{ 4331 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 4332 sizeof(ifr.ifr_name)) 4333 errx(1, "hdr prio: name is too long"); 4334 4335 if (ioctl(sock, SIOCGRXHPRIO, (caddr_t)&ifr) == -1) 4336 return; 4337 4338 ife->ife_flags |= IFE_RXHPRIO_SET; 4339 ife->ife_rxhprio = ifr.ifr_hdrprio; 4340} 4341 4342void 4343setrxprio(const char *val, int d) 4344{ 4345 const char *errmsg = NULL; 4346 4347 if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= 4348 sizeof(ifr.ifr_name)) 4349 errx(1, "rx prio: name is too long"); 4350 4351 if (strcmp(val, "packet") == 0) 4352 ifr.ifr_hdrprio = IF_HDRPRIO_PACKET; 4353 else if (strcmp(val, "payload") == 0) 4354 ifr.ifr_hdrprio = IF_HDRPRIO_PAYLOAD; 4355 else if (strcmp(val, "outer") == 0) 4356 ifr.ifr_hdrprio = IF_HDRPRIO_OUTER; 4357 else { 4358 ifr.ifr_hdrprio = strtonum(val, 4359 IF_HDRPRIO_MIN, IF_HDRPRIO_MAX, &errmsg); 4360 if (errmsg) 4361 errx(1, "rx prio %s: %s", val, errmsg); 4362 } 4363 4364 if (ioctl(sock, SIOCSRXHPRIO, (caddr_t)&ifr) == -1) 4365 warn("SIOCSRXHPRIO"); 4366} 4367#endif 4368 4369void 4370getencap(void) 4371{ 4372 struct ifencap ife = { .ife_flags = 0 }; 4373 4374 getvnetid(&ife); 4375 getvnetflowid(&ife); 4376 getifparent(&ife); 4377#ifndef SMALL 4378 gettxprio(&ife); 4379 getrxprio(&ife); 4380#endif 4381 4382 if (ife.ife_flags == 0) 4383 return; 4384 4385 printf("\tencap:"); 4386 4387 switch (ife.ife_flags & IFE_VNETID_MASK) { 4388 case IFE_VNETID_NONE: 4389 printf(" vnetid none"); 4390 break; 4391 case IFE_VNETID_ANY: 4392 printf(" vnetid any"); 4393 break; 4394 case IFE_VNETID_SET: 4395 printf(" vnetid %lld", ife.ife_vnetid); 4396 if (ife.ife_flags & IFE_VNETFLOWID) 4397 printf("+"); 4398 break; 4399 } 4400 4401 switch (ife.ife_flags & IFE_PARENT_MASK) { 4402 case IFE_PARENT_NONE: 4403 printf(" parent none"); 4404 break; 4405 case IFE_PARENT_SET: 4406 printf(" parent %s", ife.ife_parent); 4407 break; 4408 } 4409 4410#ifndef SMALL 4411 if (ife.ife_flags & IFE_TXHPRIO_SET) { 4412 printf(" txprio "); 4413 switch (ife.ife_txhprio) { 4414 case IF_HDRPRIO_PACKET: 4415 printf("packet"); 4416 break; 4417 case IF_HDRPRIO_PAYLOAD: 4418 printf("payload"); 4419 break; 4420 default: 4421 printf("%d", ife.ife_txhprio); 4422 break; 4423 } 4424 } 4425 4426 if (ife.ife_flags & IFE_RXHPRIO_SET) { 4427 printf(" rxprio "); 4428 switch (ife.ife_rxhprio) { 4429 case IF_HDRPRIO_PACKET: 4430 printf("packet"); 4431 break; 4432 case IF_HDRPRIO_PAYLOAD: 4433 printf("payload"); 4434 break; 4435 case IF_HDRPRIO_OUTER: 4436 printf("outer"); 4437 break; 4438 default: 4439 printf("%d", ife.ife_rxhprio); 4440 break; 4441 } 4442 } 4443#endif 4444 4445 printf("\n"); 4446} 4447 4448void 4449settrunkport(const char *val, int d) 4450{ 4451 struct trunk_reqport rp; 4452 4453 bzero(&rp, sizeof(rp)); 4454 strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname)); 4455 strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); 4456 4457 if (ioctl(sock, SIOCSTRUNKPORT, &rp) == -1) 4458 err(1, "%s %s: SIOCSTRUNKPORT", rp.rp_ifname, rp.rp_portname); 4459} 4460 4461void 4462unsettrunkport(const char *val, int d) 4463{ 4464 struct trunk_reqport rp; 4465 4466 bzero(&rp, sizeof(rp)); 4467 strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname)); 4468 strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); 4469 4470 if (ioctl(sock, SIOCSTRUNKDELPORT, &rp) == -1) 4471 err(1, "%s: %s: SIOCSTRUNKDELPORT", rp.rp_ifname, 4472 rp.rp_portname); 4473} 4474 4475void 4476settrunkproto(const char *val, int d) 4477{ 4478 struct trunk_protos tpr[] = TRUNK_PROTOS; 4479 struct trunk_reqall ra; 4480 int i; 4481 4482 bzero(&ra, sizeof(ra)); 4483 ra.ra_proto = TRUNK_PROTO_MAX; 4484 4485 for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) { 4486 if (strcmp(val, tpr[i].tpr_name) == 0) { 4487 ra.ra_proto = tpr[i].tpr_proto; 4488 break; 4489 } 4490 } 4491 if (ra.ra_proto == TRUNK_PROTO_MAX) 4492 errx(1, "Invalid trunk protocol: %s", val); 4493 4494 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); 4495 if (ioctl(sock, SIOCSTRUNK, &ra) != 0) 4496 err(1, "%s: SIOCSTRUNK", ra.ra_ifname); 4497} 4498 4499void 4500settrunklacpmode(const char *val, int d) 4501{ 4502 struct trunk_reqall ra; 4503 struct trunk_opts tops; 4504 4505 bzero(&ra, sizeof(ra)); 4506 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); 4507 4508 if (ioctl(sock, SIOCGTRUNK, &ra) != 0) 4509 err(1, "%s: SIOCGTRUNK", ra.ra_ifname); 4510 4511 if (ra.ra_proto != TRUNK_PROTO_LACP) 4512 errx(1, "Invalid option for trunk: %s", ifname); 4513 4514 if (strcmp(val, lacpmodeactive) != 0 && 4515 strcmp(val, lacpmodepassive) != 0) 4516 errx(1, "Invalid lacpmode option for trunk: %s", ifname); 4517 4518 bzero(&tops, sizeof(tops)); 4519 strlcpy(tops.to_ifname, ifname, sizeof(tops.to_ifname)); 4520 tops.to_proto = TRUNK_PROTO_LACP; 4521 tops.to_opts |= TRUNK_OPT_LACP_MODE; 4522 4523 if (strcmp(val, lacpmodeactive) == 0) 4524 tops.to_lacpopts.lacp_mode = 1; 4525 else 4526 tops.to_lacpopts.lacp_mode = 0; 4527 4528 if (ioctl(sock, SIOCSTRUNKOPTS, &tops) != 0) 4529 err(1, "%s: SIOCSTRUNKOPTS", tops.to_ifname); 4530} 4531 4532void 4533settrunklacptimeout(const char *val, int d) 4534{ 4535 struct trunk_reqall ra; 4536 struct trunk_opts tops; 4537 4538 bzero(&ra, sizeof(ra)); 4539 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); 4540 4541 if (ioctl(sock, SIOCGTRUNK, &ra) != 0) 4542 err(1, "%s SIOCGTRUNK", ra.ra_ifname); 4543 4544 if (ra.ra_proto != TRUNK_PROTO_LACP) 4545 errx(1, "Invalid option for trunk: %s", ifname); 4546 4547 if (strcmp(val, lacptimeoutfast) != 0 && 4548 strcmp(val, lacptimeoutslow) != 0) 4549 errx(1, "Invalid lacptimeout option for trunk: %s", ifname); 4550 4551 bzero(&tops, sizeof(tops)); 4552 strlcpy(tops.to_ifname, ifname, sizeof(tops.to_ifname)); 4553 tops.to_proto = TRUNK_PROTO_LACP; 4554 tops.to_opts |= TRUNK_OPT_LACP_TIMEOUT; 4555 4556 if (strcmp(val, lacptimeoutfast) == 0) 4557 tops.to_lacpopts.lacp_timeout = 1; 4558 else 4559 tops.to_lacpopts.lacp_timeout = 0; 4560 4561 if (ioctl(sock, SIOCSTRUNKOPTS, &tops) != 0) 4562 err(1, "%s: SIOCSTRUNKOPTS", tops.to_ifname); 4563} 4564 4565void 4566trunk_status(void) 4567{ 4568 struct trunk_protos tpr[] = TRUNK_PROTOS; 4569 struct trunk_reqport rp, rpbuf[TRUNK_MAX_PORTS]; 4570 struct trunk_reqall ra; 4571 struct lacp_opreq *lp; 4572 const char *proto = "<unknown>"; 4573 int i, isport = 0; 4574 4575 bzero(&rp, sizeof(rp)); 4576 bzero(&ra, sizeof(ra)); 4577 4578 strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname)); 4579 strlcpy(rp.rp_portname, ifname, sizeof(rp.rp_portname)); 4580 4581 if (ioctl(sock, SIOCGTRUNKPORT, &rp) == 0) 4582 isport = 1; 4583 4584 strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); 4585 ra.ra_size = sizeof(rpbuf); 4586 ra.ra_port = rpbuf; 4587 4588 if (ioctl(sock, SIOCGTRUNK, &ra) == 0) { 4589 lp = (struct lacp_opreq *)&ra.ra_lacpreq; 4590 4591 for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) { 4592 if (ra.ra_proto == tpr[i].tpr_proto) { 4593 proto = tpr[i].tpr_name; 4594 break; 4595 } 4596 } 4597 4598 printf("\ttrunk: trunkproto %s", proto); 4599 if (isport) 4600 printf(" trunkdev %s", rp.rp_ifname); 4601 putchar('\n'); 4602 if (ra.ra_proto == TRUNK_PROTO_LACP) { 4603 char *act_mac = strdup( 4604 ether_ntoa((struct ether_addr*)lp->actor_mac)); 4605 if (act_mac == NULL) 4606 err(1, "strdup"); 4607 printf("\ttrunk id: [(%04X,%s,%04X,%04X,%04X),\n" 4608 "\t\t (%04X,%s,%04X,%04X,%04X)]\n", 4609 lp->actor_prio, act_mac, 4610 lp->actor_key, lp->actor_portprio, lp->actor_portno, 4611 lp->partner_prio, 4612 ether_ntoa((struct ether_addr*)lp->partner_mac), 4613 lp->partner_key, lp->partner_portprio, 4614 lp->partner_portno); 4615 free(act_mac); 4616 } 4617 4618 for (i = 0; i < ra.ra_ports; i++) { 4619 lp = (struct lacp_opreq *)&(rpbuf[i].rp_lacpreq); 4620 if (ra.ra_proto == TRUNK_PROTO_LACP) { 4621 printf("\t\t%s lacp actor " 4622 "system pri 0x%x mac %s, key 0x%x, " 4623 "port pri 0x%x number 0x%x\n", 4624 rpbuf[i].rp_portname, 4625 lp->actor_prio, 4626 ether_ntoa((struct ether_addr*) 4627 lp->actor_mac), 4628 lp->actor_key, 4629 lp->actor_portprio, lp->actor_portno); 4630 printf("\t\t%s lacp actor state ", 4631 rpbuf[i].rp_portname); 4632 printb_status(lp->actor_state, 4633 LACP_STATE_BITS); 4634 putchar('\n'); 4635 4636 printf("\t\t%s lacp partner " 4637 "system pri 0x%x mac %s, key 0x%x, " 4638 "port pri 0x%x number 0x%x\n", 4639 rpbuf[i].rp_portname, 4640 lp->partner_prio, 4641 ether_ntoa((struct ether_addr*) 4642 lp->partner_mac), 4643 lp->partner_key, 4644 lp->partner_portprio, lp->partner_portno); 4645 printf("\t\t%s lacp partner state ", 4646 rpbuf[i].rp_portname); 4647 printb_status(lp->partner_state, 4648 LACP_STATE_BITS); 4649 putchar('\n'); 4650 } 4651 4652 printf("\t\t%s port ", rpbuf[i].rp_portname); 4653 printb_status(rpbuf[i].rp_flags, TRUNK_PORT_BITS); 4654 putchar('\n'); 4655 } 4656 4657 if (showmediaflag) { 4658 printf("\tsupported trunk protocols:\n"); 4659 for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) 4660 printf("\t\ttrunkproto %s\n", tpr[i].tpr_name); 4661 } 4662 } else if (isport) 4663 printf("\ttrunk: trunkdev %s\n", rp.rp_ifname); 4664} 4665 4666#ifndef SMALL 4667static const char *carp_states[] = { CARP_STATES }; 4668static const char *carp_bal_modes[] = { CARP_BAL_MODES }; 4669 4670void 4671carp_status(void) 4672{ 4673 const char *state, *balmode; 4674 struct carpreq carpr; 4675 char peer[32]; 4676 int i; 4677 4678 memset((char *)&carpr, 0, sizeof(struct carpreq)); 4679 ifr.ifr_data = (caddr_t)&carpr; 4680 4681 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4682 return; 4683 4684 if (carpr.carpr_vhids[0] == 0) 4685 return; 4686 4687 if (carpr.carpr_balancing > CARP_BAL_MAXID) 4688 balmode = "<UNKNOWN>"; 4689 else 4690 balmode = carp_bal_modes[carpr.carpr_balancing]; 4691 4692 if (carpr.carpr_peer.s_addr != htonl(INADDR_CARP_GROUP)) 4693 snprintf(peer, sizeof(peer), 4694 " carppeer %s", inet_ntoa(carpr.carpr_peer)); 4695 else 4696 peer[0] = '\0'; 4697 4698 for (i = 0; carpr.carpr_vhids[i]; i++) { 4699 if (carpr.carpr_states[i] > CARP_MAXSTATE) 4700 state = "<UNKNOWN>"; 4701 else 4702 state = carp_states[carpr.carpr_states[i]]; 4703 if (carpr.carpr_vhids[1] == 0) { 4704 printf("\tcarp: %s carpdev %s vhid %u advbase %d " 4705 "advskew %u%s\n", state, 4706 carpr.carpr_carpdev[0] != '\0' ? 4707 carpr.carpr_carpdev : "none", carpr.carpr_vhids[0], 4708 carpr.carpr_advbase, carpr.carpr_advskews[0], 4709 peer); 4710 } else { 4711 if (i == 0) { 4712 printf("\tcarp: carpdev %s advbase %d" 4713 " balancing %s%s\n", 4714 carpr.carpr_carpdev[0] != '\0' ? 4715 carpr.carpr_carpdev : "none", 4716 carpr.carpr_advbase, balmode, peer); 4717 } 4718 printf("\t\tstate %s vhid %u advskew %u\n", state, 4719 carpr.carpr_vhids[i], carpr.carpr_advskews[i]); 4720 } 4721 } 4722} 4723 4724void 4725setcarp_passwd(const char *val, int d) 4726{ 4727 struct carpreq carpr; 4728 4729 bzero(&carpr, sizeof(struct carpreq)); 4730 ifr.ifr_data = (caddr_t)&carpr; 4731 4732 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4733 err(1, "%s: SIOCGVH", ifr.ifr_name); 4734 4735 bzero(carpr.carpr_key, CARP_KEY_LEN); 4736 strlcpy((char *)carpr.carpr_key, val, CARP_KEY_LEN); 4737 4738 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4739 err(1, "%s: SIOCSVH", ifr.ifr_name); 4740} 4741 4742void 4743setcarp_vhid(const char *val, int d) 4744{ 4745 const char *errmsg = NULL; 4746 struct carpreq carpr; 4747 int vhid; 4748 4749 vhid = strtonum(val, 1, 255, &errmsg); 4750 if (errmsg) 4751 errx(1, "vhid %s: %s", val, errmsg); 4752 4753 bzero(&carpr, sizeof(struct carpreq)); 4754 ifr.ifr_data = (caddr_t)&carpr; 4755 4756 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4757 err(1, "%s: SIOCGVH", ifr.ifr_name); 4758 4759 carpr.carpr_vhids[0] = vhid; 4760 carpr.carpr_vhids[1] = 0; 4761 4762 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4763 err(1, "%s: SIOCSVH", ifr.ifr_name); 4764} 4765 4766void 4767setcarp_advskew(const char *val, int d) 4768{ 4769 const char *errmsg = NULL; 4770 struct carpreq carpr; 4771 int advskew; 4772 4773 advskew = strtonum(val, 0, 254, &errmsg); 4774 if (errmsg) 4775 errx(1, "advskew %s: %s", val, errmsg); 4776 4777 bzero(&carpr, sizeof(struct carpreq)); 4778 ifr.ifr_data = (caddr_t)&carpr; 4779 4780 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4781 err(1, "%s: SIOCGVH", ifr.ifr_name); 4782 4783 carpr.carpr_advskews[0] = advskew; 4784 4785 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4786 err(1, "%s: SIOCSVH", ifr.ifr_name); 4787} 4788 4789void 4790setcarp_advbase(const char *val, int d) 4791{ 4792 const char *errmsg = NULL; 4793 struct carpreq carpr; 4794 int advbase; 4795 4796 advbase = strtonum(val, 0, 254, &errmsg); 4797 if (errmsg) 4798 errx(1, "advbase %s: %s", val, errmsg); 4799 4800 bzero(&carpr, sizeof(struct carpreq)); 4801 ifr.ifr_data = (caddr_t)&carpr; 4802 4803 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4804 err(1, "%s: SIOCGVH", ifr.ifr_name); 4805 4806 carpr.carpr_advbase = advbase; 4807 4808 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4809 err(1, "%s: SIOCSVH", ifr.ifr_name); 4810} 4811 4812void 4813setcarppeer(const char *val, int d) 4814{ 4815 struct carpreq carpr; 4816 struct addrinfo hints, *peerres; 4817 int ecode; 4818 4819 bzero(&carpr, sizeof(struct carpreq)); 4820 ifr.ifr_data = (caddr_t)&carpr; 4821 4822 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4823 err(1, "%s: SIOCGVH", ifr.ifr_name); 4824 4825 bzero(&hints, sizeof(hints)); 4826 hints.ai_family = AF_INET; 4827 hints.ai_socktype = SOCK_DGRAM; 4828 4829 if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0) 4830 errx(1, "error in parsing address string: %s", 4831 gai_strerror(ecode)); 4832 4833 if (peerres->ai_addr->sa_family != AF_INET) 4834 errx(1, "only IPv4 addresses supported for the carppeer"); 4835 4836 carpr.carpr_peer.s_addr = ((struct sockaddr_in *) 4837 peerres->ai_addr)->sin_addr.s_addr; 4838 4839 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4840 err(1, "%s: SIOCSVH", ifr.ifr_name); 4841 4842 freeaddrinfo(peerres); 4843} 4844 4845void 4846unsetcarppeer(const char *val, int d) 4847{ 4848 struct carpreq carpr; 4849 4850 bzero(&carpr, sizeof(struct carpreq)); 4851 ifr.ifr_data = (caddr_t)&carpr; 4852 4853 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4854 err(1, "%s: SIOCGVH", ifr.ifr_name); 4855 4856 bzero(&carpr.carpr_peer, sizeof(carpr.carpr_peer)); 4857 4858 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4859 err(1, "%s: SIOCSVH", ifr.ifr_name); 4860} 4861 4862void 4863setcarp_state(const char *val, int d) 4864{ 4865 struct carpreq carpr; 4866 int i; 4867 4868 bzero(&carpr, sizeof(struct carpreq)); 4869 ifr.ifr_data = (caddr_t)&carpr; 4870 4871 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4872 err(1, "%s: SIOCGVH", ifr.ifr_name); 4873 4874 for (i = 0; i <= CARP_MAXSTATE; i++) { 4875 if (!strcasecmp(val, carp_states[i])) { 4876 carpr.carpr_state = i; 4877 break; 4878 } 4879 } 4880 4881 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4882 err(1, "%s: SIOCSVH", ifr.ifr_name); 4883} 4884 4885void 4886setcarpdev(const char *val, int d) 4887{ 4888 struct carpreq carpr; 4889 4890 bzero(&carpr, sizeof(struct carpreq)); 4891 ifr.ifr_data = (caddr_t)&carpr; 4892 4893 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4894 err(1, "%s: SIOCGVH", ifr.ifr_name); 4895 4896 strlcpy(carpr.carpr_carpdev, val, sizeof(carpr.carpr_carpdev)); 4897 4898 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4899 err(1, "%s: SIOCSVH", ifr.ifr_name); 4900} 4901 4902void 4903setcarp_nodes(const char *val, int d) 4904{ 4905 char *optlist, *str; 4906 int i; 4907 struct carpreq carpr; 4908 4909 bzero(&carpr, sizeof(struct carpreq)); 4910 ifr.ifr_data = (caddr_t)&carpr; 4911 4912 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4913 err(1, "%s: SIOCGVH", ifr.ifr_name); 4914 4915 bzero(carpr.carpr_vhids, sizeof(carpr.carpr_vhids)); 4916 bzero(carpr.carpr_advskews, sizeof(carpr.carpr_advskews)); 4917 4918 optlist = strdup(val); 4919 if (optlist == NULL) 4920 err(1, "strdup"); 4921 4922 str = strtok(optlist, ","); 4923 for (i = 0; str != NULL; i++) { 4924 u_int vhid, advskew; 4925 4926 if (i >= CARP_MAXNODES) 4927 errx(1, "too many carp nodes"); 4928 if (sscanf(str, "%u:%u", &vhid, &advskew) != 2) { 4929 errx(1, "non parsable arg: %s", str); 4930 } 4931 if (vhid > 255) 4932 errx(1, "vhid %u: value too large", vhid); 4933 if (advskew >= 255) 4934 errx(1, "advskew %u: value too large", advskew); 4935 4936 carpr.carpr_vhids[i] = vhid; 4937 carpr.carpr_advskews[i] = advskew; 4938 str = strtok(NULL, ","); 4939 } 4940 free(optlist); 4941 4942 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4943 err(1, "%s: SIOCSVH", ifr.ifr_name); 4944} 4945 4946void 4947setcarp_balancing(const char *val, int d) 4948{ 4949 int i; 4950 struct carpreq carpr; 4951 4952 bzero(&carpr, sizeof(struct carpreq)); 4953 ifr.ifr_data = (caddr_t)&carpr; 4954 4955 if (ioctl(sock, SIOCGVH, (caddr_t)&ifr) == -1) 4956 err(1, "%s: SIOCGVH", ifr.ifr_name); 4957 4958 for (i = 0; i <= CARP_BAL_MAXID; i++) 4959 if (!strcasecmp(val, carp_bal_modes[i])) 4960 break; 4961 4962 if (i > CARP_BAL_MAXID) 4963 errx(1, "balancing %s: unknown mode", val); 4964 4965 carpr.carpr_balancing = i; 4966 4967 if (ioctl(sock, SIOCSVH, (caddr_t)&ifr) == -1) 4968 err(1, "%s: SIOCSVH", ifr.ifr_name); 4969} 4970 4971void 4972setpfsync_syncdev(const char *val, int d) 4973{ 4974 struct pfsyncreq preq; 4975 4976 bzero(&preq, sizeof(struct pfsyncreq)); 4977 ifr.ifr_data = (caddr_t)&preq; 4978 4979 if (ioctl(sock, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) 4980 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); 4981 4982 strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev)); 4983 4984 if (ioctl(sock, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) 4985 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); 4986} 4987 4988void 4989unsetpfsync_syncdev(const char *val, int d) 4990{ 4991 struct pfsyncreq preq; 4992 4993 bzero(&preq, sizeof(struct pfsyncreq)); 4994 ifr.ifr_data = (caddr_t)&preq; 4995 4996 if (ioctl(sock, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) 4997 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); 4998 4999 bzero(&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev)); 5000 5001 if (ioctl(sock, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) 5002 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); 5003} 5004 5005void 5006setpfsync_syncpeer(const char *val, int d) 5007{ 5008 struct pfsyncreq preq; 5009 struct addrinfo hints, *peerres; 5010 int ecode; 5011 5012 bzero(&preq, sizeof(struct pfsyncreq)); 5013 ifr.ifr_data = (caddr_t)&preq; 5014 5015 if (ioctl(sock, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) 5016 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); 5017 5018 memset(&hints, 0, sizeof(hints)); 5019 hints.ai_family = AF_INET; 5020 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 5021 5022 if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0) 5023 errx(1, "error in parsing address string: %s", 5024 gai_strerror(ecode)); 5025 5026 if (peerres->ai_addr->sa_family != AF_INET) 5027 errx(1, "only IPv4 addresses supported for the syncpeer"); 5028 5029 preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *) 5030 peerres->ai_addr)->sin_addr.s_addr; 5031 5032 if (ioctl(sock, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) 5033 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); 5034 5035 freeaddrinfo(peerres); 5036} 5037 5038void 5039unsetpfsync_syncpeer(const char *val, int d) 5040{ 5041 struct pfsyncreq preq; 5042 5043 bzero(&preq, sizeof(struct pfsyncreq)); 5044 ifr.ifr_data = (caddr_t)&preq; 5045 5046 if (ioctl(sock, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) 5047 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); 5048 5049 preq.pfsyncr_syncpeer.s_addr = 0; 5050 5051 if (ioctl(sock, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) 5052 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); 5053} 5054 5055void 5056setpfsync_maxupd(const char *val, int d) 5057{ 5058 const char *errmsg = NULL; 5059 struct pfsyncreq preq; 5060 int maxupdates; 5061 5062 maxupdates = strtonum(val, 0, 255, &errmsg); 5063 if (errmsg) 5064 errx(1, "maxupd %s: %s", val, errmsg); 5065 5066 bzero(&preq, sizeof(struct pfsyncreq)); 5067 ifr.ifr_data = (caddr_t)&preq; 5068 5069 if (ioctl(sock, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) 5070 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); 5071 5072 preq.pfsyncr_maxupdates = maxupdates; 5073 5074 if (ioctl(sock, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) 5075 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); 5076} 5077 5078void 5079setpfsync_defer(const char *val, int d) 5080{ 5081 struct pfsyncreq preq; 5082 5083 bzero(&preq, sizeof(struct pfsyncreq)); 5084 ifr.ifr_data = (caddr_t)&preq; 5085 5086 if (ioctl(sock, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) 5087 err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); 5088 5089 preq.pfsyncr_defer = d; 5090 if (ioctl(sock, SIOCSETPFSYNC, (caddr_t)&ifr) == -1) 5091 err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); 5092} 5093 5094void 5095pfsync_status(void) 5096{ 5097 struct pfsyncreq preq; 5098 5099 bzero(&preq, sizeof(struct pfsyncreq)); 5100 ifr.ifr_data = (caddr_t)&preq; 5101 5102 if (ioctl(sock, SIOCGETPFSYNC, (caddr_t)&ifr) == -1) 5103 return; 5104 5105 if (preq.pfsyncr_syncdev[0] != '\0') { 5106 printf("\tpfsync: syncdev: %s ", preq.pfsyncr_syncdev); 5107 if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) 5108 printf("syncpeer: %s ", 5109 inet_ntoa(preq.pfsyncr_syncpeer)); 5110 printf("maxupd: %d ", preq.pfsyncr_maxupdates); 5111 printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off"); 5112 } 5113} 5114 5115void 5116pflow_status(void) 5117{ 5118 struct pflowreq preq; 5119 struct sockaddr_in *sin; 5120 struct sockaddr_in6 *sin6; 5121 int error; 5122 char buf[INET6_ADDRSTRLEN]; 5123 5124 bzero(&preq, sizeof(struct pflowreq)); 5125 ifr.ifr_data = (caddr_t)&preq; 5126 5127 if (ioctl(sock, SIOCGETPFLOW, (caddr_t)&ifr) == -1) 5128 return; 5129 5130 if (preq.flowsrc.ss_family == AF_INET || preq.flowsrc.ss_family == 5131 AF_INET6) { 5132 error = getnameinfo((struct sockaddr*)&preq.flowsrc, 5133 preq.flowsrc.ss_len, buf, sizeof(buf), NULL, 0, 5134 NI_NUMERICHOST); 5135 if (error) 5136 err(1, "sender: %s", gai_strerror(error)); 5137 } 5138 5139 printf("\tpflow: "); 5140 switch (preq.flowsrc.ss_family) { 5141 case AF_INET: 5142 sin = (struct sockaddr_in*) &preq.flowsrc; 5143 if (sin->sin_addr.s_addr != INADDR_ANY) { 5144 printf("sender: %s", buf); 5145 if (sin->sin_port != 0) 5146 printf(":%u", ntohs(sin->sin_port)); 5147 printf(" "); 5148 } 5149 break; 5150 case AF_INET6: 5151 sin6 = (struct sockaddr_in6*) &preq.flowsrc; 5152 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 5153 printf("sender: [%s]", buf); 5154 if (sin6->sin6_port != 0) 5155 printf(":%u", ntohs(sin6->sin6_port)); 5156 printf(" "); 5157 } 5158 default: 5159 break; 5160 } 5161 if (preq.flowdst.ss_family == AF_INET || preq.flowdst.ss_family == 5162 AF_INET6) { 5163 error = getnameinfo((struct sockaddr*)&preq.flowdst, 5164 preq.flowdst.ss_len, buf, sizeof(buf), NULL, 0, 5165 NI_NUMERICHOST); 5166 if (error) 5167 err(1, "receiver: %s", gai_strerror(error)); 5168 } 5169 switch (preq.flowdst.ss_family) { 5170 case AF_INET: 5171 sin = (struct sockaddr_in*)&preq.flowdst; 5172 printf("receiver: %s:", sin->sin_addr.s_addr != INADDR_ANY ? 5173 buf : "INVALID"); 5174 if (sin->sin_port == 0) 5175 printf("%s ", "INVALID"); 5176 else 5177 printf("%u ", ntohs(sin->sin_port)); 5178 break; 5179 case AF_INET6: 5180 sin6 = (struct sockaddr_in6*) &preq.flowdst; 5181 printf("receiver: [%s]:", 5182 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ? buf : 5183 "INVALID"); 5184 if (sin6->sin6_port == 0) 5185 printf("%s ", "INVALID"); 5186 else 5187 printf("%u ", ntohs(sin6->sin6_port)); 5188 break; 5189 default: 5190 printf("receiver: INVALID:INVALID "); 5191 break; 5192 } 5193 printf("version: %d\n", preq.version); 5194} 5195 5196void 5197pflow_addr(const char *val, struct sockaddr_storage *ss) { 5198 struct addrinfo hints, *res0; 5199 int error, flag; 5200 char *cp, *ip, *port, buf[HOST_NAME_MAX+1 + sizeof (":65535")]; 5201 5202 if (strlcpy(buf, val, sizeof(buf)) >= sizeof(buf)) 5203 errx(1, "%s bad value", val); 5204 5205 port = NULL; 5206 cp = buf; 5207 if (*cp == '[') 5208 flag = 1; 5209 else 5210 flag = 0; 5211 5212 for(; *cp; ++cp) { 5213 if (*cp == ']' && *(cp + 1) == ':' && flag) { 5214 *cp = '\0'; 5215 *(cp + 1) = '\0'; 5216 port = cp + 2; 5217 break; 5218 } 5219 if (*cp == ']' && *(cp + 1) == '\0' && flag) { 5220 *cp = '\0'; 5221 port = NULL; 5222 break; 5223 } 5224 if (*cp == ':' && !flag) { 5225 *cp = '\0'; 5226 port = cp + 1; 5227 break; 5228 } 5229 } 5230 5231 ip = buf; 5232 if (flag) 5233 ip++; 5234 5235 bzero(&hints, sizeof(hints)); 5236 hints.ai_family = AF_UNSPEC; 5237 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 5238 hints.ai_flags = AI_NUMERICHOST; 5239 5240 if ((error = getaddrinfo(ip, port, &hints, &res0)) != 0) 5241 errx(1, "error in parsing address string: %s", 5242 gai_strerror(error)); 5243 5244 memcpy(ss, res0->ai_addr, res0->ai_addr->sa_len); 5245 freeaddrinfo(res0); 5246} 5247 5248void 5249setpflow_sender(const char *val, int d) 5250{ 5251 struct pflowreq preq; 5252 5253 bzero(&preq, sizeof(struct pflowreq)); 5254 ifr.ifr_data = (caddr_t)&preq; 5255 preq.addrmask |= PFLOW_MASK_SRCIP; 5256 pflow_addr(val, &preq.flowsrc); 5257 5258 if (ioctl(sock, SIOCSETPFLOW, (caddr_t)&ifr) == -1) 5259 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); 5260} 5261 5262void 5263unsetpflow_sender(const char *val, int d) 5264{ 5265 struct pflowreq preq; 5266 5267 bzero(&preq, sizeof(struct pflowreq)); 5268 preq.addrmask |= PFLOW_MASK_SRCIP; 5269 ifr.ifr_data = (caddr_t)&preq; 5270 if (ioctl(sock, SIOCSETPFLOW, (caddr_t)&ifr) == -1) 5271 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); 5272} 5273 5274void 5275setpflow_receiver(const char *val, int d) 5276{ 5277 struct pflowreq preq; 5278 5279 bzero(&preq, sizeof(struct pflowreq)); 5280 ifr.ifr_data = (caddr_t)&preq; 5281 preq.addrmask |= PFLOW_MASK_DSTIP; 5282 pflow_addr(val, &preq.flowdst); 5283 5284 if (ioctl(sock, SIOCSETPFLOW, (caddr_t)&ifr) == -1) 5285 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); 5286} 5287 5288void 5289unsetpflow_receiver(const char *val, int d) 5290{ 5291 struct pflowreq preq; 5292 5293 bzero(&preq, sizeof(struct pflowreq)); 5294 ifr.ifr_data = (caddr_t)&preq; 5295 preq.addrmask |= PFLOW_MASK_DSTIP; 5296 if (ioctl(sock, SIOCSETPFLOW, (caddr_t)&ifr) == -1) 5297 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); 5298} 5299 5300/* PFLOWPROTO XXX */ 5301void 5302setpflowproto(const char *val, int d) 5303{ 5304 struct pflow_protos ppr[] = PFLOW_PROTOS; 5305 struct pflowreq preq; 5306 int i; 5307 5308 bzero(&preq, sizeof(preq)); 5309 preq.version = PFLOW_PROTO_MAX; 5310 5311 for (i = 0; i < (sizeof(ppr) / sizeof(ppr[0])); i++) { 5312 if (strcmp(val, ppr[i].ppr_name) == 0) { 5313 preq.version = ppr[i].ppr_proto; 5314 break; 5315 } 5316 } 5317 if (preq.version == PFLOW_PROTO_MAX) 5318 errx(1, "Invalid pflow protocol: %s", val); 5319 5320 preq.addrmask |= PFLOW_MASK_VERSION; 5321 5322 ifr.ifr_data = (caddr_t)&preq; 5323 5324 if (ioctl(sock, SIOCSETPFLOW, (caddr_t)&ifr) == -1) 5325 err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); 5326} 5327 5328void 5329pppoe_status(void) 5330{ 5331 struct pppoediscparms parms; 5332 struct pppoeconnectionstate state; 5333 5334 memset(&state, 0, sizeof(state)); 5335 5336 strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); 5337 if (ioctl(sock, PPPOEGETPARMS, &parms) == -1) 5338 return; 5339 5340 printf("\tdev: %s ", parms.eth_ifname); 5341 5342 if (*parms.ac_name) 5343 printf("ac: %s ", parms.ac_name); 5344 if (*parms.service_name) 5345 printf("svc: %s ", parms.service_name); 5346 5347 strlcpy(state.ifname, ifname, sizeof(state.ifname)); 5348 if (ioctl(sock, PPPOEGETSESSION, &state) == -1) 5349 err(1, "PPPOEGETSESSION"); 5350 5351 printf("state: "); 5352 switch (state.state) { 5353 case PPPOE_STATE_INITIAL: 5354 printf("initial"); break; 5355 case PPPOE_STATE_PADI_SENT: 5356 printf("PADI sent"); break; 5357 case PPPOE_STATE_PADR_SENT: 5358 printf("PADR sent"); break; 5359 case PPPOE_STATE_SESSION: 5360 printf("session"); break; 5361 case PPPOE_STATE_CLOSING: 5362 printf("closing"); break; 5363 } 5364 printf("\n\tsid: 0x%x", state.session_id); 5365 printf(" PADI retries: %d", state.padi_retry_no); 5366 printf(" PADR retries: %d", state.padr_retry_no); 5367 5368 if (state.state == PPPOE_STATE_SESSION) { 5369 struct timespec temp_time; 5370 time_t diff_time, day = 0; 5371 unsigned int hour = 0, min = 0, sec = 0; 5372 5373 if (state.session_time.tv_sec != 0) { 5374 if (clock_gettime(CLOCK_BOOTTIME, &temp_time) == -1) 5375 goto notime; 5376 diff_time = temp_time.tv_sec - 5377 state.session_time.tv_sec; 5378 5379 day = diff_time / (60 * 60 * 24); 5380 diff_time %= (60 * 60 * 24); 5381 5382 hour = diff_time / (60 * 60); 5383 diff_time %= (60 * 60); 5384 5385 min = diff_time / 60; 5386 diff_time %= 60; 5387 5388 sec = diff_time; 5389 } 5390 printf(" time: "); 5391 if (day != 0) 5392 printf("%lldd ", (long long)day); 5393 printf("%02u:%02u:%02u", hour, min, sec); 5394 } 5395notime: 5396 putchar('\n'); 5397} 5398 5399void 5400setpppoe_dev(const char *val, int d) 5401{ 5402 struct pppoediscparms parms; 5403 5404 strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); 5405 if (ioctl(sock, PPPOEGETPARMS, &parms) == -1) 5406 return; 5407 5408 strlcpy(parms.eth_ifname, val, sizeof(parms.eth_ifname)); 5409 5410 if (ioctl(sock, PPPOESETPARMS, &parms) == -1) 5411 err(1, "PPPOESETPARMS"); 5412} 5413 5414void 5415setpppoe_svc(const char *val, int d) 5416{ 5417 struct pppoediscparms parms; 5418 5419 strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); 5420 if (ioctl(sock, PPPOEGETPARMS, &parms) == -1) 5421 return; 5422 5423 if (d == 0) 5424 strlcpy(parms.service_name, val, sizeof(parms.service_name)); 5425 else 5426 memset(parms.service_name, 0, sizeof(parms.service_name)); 5427 5428 if (ioctl(sock, PPPOESETPARMS, &parms) == -1) 5429 err(1, "PPPOESETPARMS"); 5430} 5431 5432void 5433setpppoe_ac(const char *val, int d) 5434{ 5435 struct pppoediscparms parms; 5436 5437 strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); 5438 if (ioctl(sock, PPPOEGETPARMS, &parms) == -1) 5439 return; 5440 5441 if (d == 0) 5442 strlcpy(parms.ac_name, val, sizeof(parms.ac_name)); 5443 else 5444 memset(parms.ac_name, 0, sizeof(parms.ac_name)); 5445 5446 if (ioctl(sock, PPPOESETPARMS, &parms) == -1) 5447 err(1, "PPPOESETPARMS"); 5448} 5449 5450void 5451spppauthinfo(struct sauthreq *spa, int d) 5452{ 5453 bzero(spa, sizeof(struct sauthreq)); 5454 5455 ifr.ifr_data = (caddr_t)spa; 5456 spa->cmd = d == 0 ? SPPPIOGMAUTH : SPPPIOGHAUTH; 5457 if (ioctl(sock, SIOCGSPPPPARAMS, &ifr) == -1) 5458 err(1, "%s: SIOCGSPPPPARAMS(SPPPIOGXAUTH)", ifr.ifr_name); 5459} 5460 5461void 5462spppdnsinfo(struct sdnsreq *spd) 5463{ 5464 memset(spd, 0, sizeof(*spd)); 5465 5466 ifr.ifr_data = (caddr_t)spd; 5467 spd->cmd = SPPPIOGDNS; 5468 if (ioctl(sock, SIOCGSPPPPARAMS, &ifr) == -1) 5469 err(1, "%s: SIOCGSPPPPARAMS(SPPPIOGDNS)", ifr.ifr_name); 5470} 5471 5472void 5473setspppproto(const char *val, int d) 5474{ 5475 struct sauthreq spa; 5476 5477 spppauthinfo(&spa, d); 5478 5479 if (strcmp(val, "pap") == 0) 5480 spa.proto = PPP_PAP; 5481 else if (strcmp(val, "chap") == 0) 5482 spa.proto = PPP_CHAP; 5483 else if (strcmp(val, "none") == 0) 5484 spa.proto = 0; 5485 else 5486 errx(1, "setpppproto"); 5487 5488 spa.cmd = d == 0 ? SPPPIOSMAUTH : SPPPIOSHAUTH; 5489 if (ioctl(sock, SIOCSSPPPPARAMS, &ifr) == -1) 5490 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); 5491} 5492 5493void 5494setsppppeerproto(const char *val, int d) 5495{ 5496 setspppproto(val, 1); 5497} 5498 5499void 5500setspppname(const char *val, int d) 5501{ 5502 struct sauthreq spa; 5503 5504 spppauthinfo(&spa, d); 5505 5506 if (spa.proto == 0) 5507 errx(1, "unspecified protocol"); 5508 if (strlcpy(spa.name, val, sizeof(spa.name)) >= sizeof(spa.name)) 5509 errx(1, "setspppname"); 5510 5511 spa.cmd = d == 0 ? SPPPIOSMAUTH : SPPPIOSHAUTH; 5512 if (ioctl(sock, SIOCSSPPPPARAMS, &ifr) == -1) 5513 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); 5514} 5515 5516void 5517setsppppeername(const char *val, int d) 5518{ 5519 setspppname(val, 1); 5520} 5521 5522void 5523setspppkey(const char *val, int d) 5524{ 5525 struct sauthreq spa; 5526 5527 spppauthinfo(&spa, d); 5528 5529 if (spa.proto == 0) 5530 errx(1, "unspecified protocol"); 5531 if (strlcpy(spa.secret, val, sizeof(spa.secret)) >= sizeof(spa.secret)) 5532 errx(1, "setspppkey"); 5533 5534 spa.cmd = d == 0 ? SPPPIOSMAUTH : SPPPIOSHAUTH; 5535 if (ioctl(sock, SIOCSSPPPPARAMS, &ifr) == -1) 5536 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); 5537} 5538 5539void 5540setsppppeerkey(const char *val, int d) 5541{ 5542 setspppkey(val, 1); 5543} 5544 5545void 5546setsppppeerflag(const char *val, int d) 5547{ 5548 struct sauthreq spa; 5549 int flag; 5550 5551 spppauthinfo(&spa, 1); 5552 5553 if (spa.proto == 0) 5554 errx(1, "unspecified protocol"); 5555 if (strcmp(val, "callin") == 0) 5556 flag = AUTHFLAG_NOCALLOUT; 5557 else if (strcmp(val, "norechallenge") == 0) 5558 flag = AUTHFLAG_NORECHALLENGE; 5559 else 5560 errx(1, "setppppeerflags"); 5561 5562 if (d) 5563 spa.flags &= ~flag; 5564 else 5565 spa.flags |= flag; 5566 5567 spa.cmd = SPPPIOSHAUTH; 5568 if (ioctl(sock, SIOCSSPPPPARAMS, &ifr) == -1) 5569 err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); 5570} 5571 5572void 5573unsetsppppeerflag(const char *val, int d) 5574{ 5575 setsppppeerflag(val, 1); 5576} 5577 5578void 5579sppp_printproto(const char *name, struct sauthreq *auth) 5580{ 5581 if (auth->proto == 0) 5582 return; 5583 printf("%sproto ", name); 5584 switch (auth->proto) { 5585 case PPP_PAP: 5586 printf("pap "); 5587 break; 5588 case PPP_CHAP: 5589 printf("chap "); 5590 break; 5591 default: 5592 printf("0x%04x ", auth->proto); 5593 break; 5594 } 5595 if (auth->name[0]) 5596 printf("%sname \"%s\" ", name, auth->name); 5597 if (auth->secret[0]) 5598 printf("%skey \"%s\" ", name, auth->secret); 5599} 5600 5601void 5602sppp_status(void) 5603{ 5604 struct spppreq spr; 5605 struct sauthreq spa; 5606 struct sdnsreq spd; 5607 char astr[INET_ADDRSTRLEN]; 5608 int i, n; 5609 5610 bzero(&spr, sizeof(spr)); 5611 5612 ifr.ifr_data = (caddr_t)&spr; 5613 spr.cmd = SPPPIOGDEFS; 5614 if (ioctl(sock, SIOCGSPPPPARAMS, &ifr) == -1) { 5615 return; 5616 } 5617 5618 if (spr.phase == PHASE_DEAD) 5619 return; 5620 printf("\tsppp: phase "); 5621 switch (spr.phase) { 5622 case PHASE_ESTABLISH: 5623 printf("establish "); 5624 break; 5625 case PHASE_TERMINATE: 5626 printf("terminate "); 5627 break; 5628 case PHASE_AUTHENTICATE: 5629 printf("authenticate "); 5630 break; 5631 case PHASE_NETWORK: 5632 printf("network "); 5633 break; 5634 default: 5635 printf("illegal "); 5636 break; 5637 } 5638 5639 spppauthinfo(&spa, 0); 5640 sppp_printproto("auth", &spa); 5641 spppauthinfo(&spa, 1); 5642 sppp_printproto("peer", &spa); 5643 if (spa.flags & AUTHFLAG_NOCALLOUT) 5644 printf("callin "); 5645 if (spa.flags & AUTHFLAG_NORECHALLENGE) 5646 printf("norechallenge "); 5647 putchar('\n'); 5648 5649 spppdnsinfo(&spd); 5650 for (i = 0, n = 0; i < IPCP_MAX_DNSSRV; i++) { 5651 if (spd.dns[i].s_addr == INADDR_ANY) 5652 break; 5653 printf("%s %s", n++ ? "" : "\tdns:", 5654 inet_ntop(AF_INET, &spd.dns[i], astr, sizeof(astr))); 5655 } 5656 if (n) 5657 printf("\n"); 5658} 5659 5660void 5661setkeepalive(const char *timeout, const char *count) 5662{ 5663 const char *errmsg = NULL; 5664 struct ifkalivereq ikar; 5665 int t, c; 5666 5667 t = strtonum(timeout, 1, 3600, &errmsg); 5668 if (errmsg) 5669 errx(1, "keepalive period %s: %s", timeout, errmsg); 5670 c = strtonum(count, 2, 600, &errmsg); 5671 if (errmsg) 5672 errx(1, "keepalive count %s: %s", count, errmsg); 5673 5674 strlcpy(ikar.ikar_name, ifname, sizeof(ikar.ikar_name)); 5675 ikar.ikar_timeo = t; 5676 ikar.ikar_cnt = c; 5677 if (ioctl(sock, SIOCSETKALIVE, (caddr_t)&ikar) == -1) 5678 warn("SIOCSETKALIVE"); 5679} 5680 5681void 5682unsetkeepalive(const char *val, int d) 5683{ 5684 struct ifkalivereq ikar; 5685 5686 bzero(&ikar, sizeof(ikar)); 5687 strlcpy(ikar.ikar_name, ifname, sizeof(ikar.ikar_name)); 5688 if (ioctl(sock, SIOCSETKALIVE, (caddr_t)&ikar) == -1) 5689 warn("SIOCSETKALIVE"); 5690} 5691 5692void 5693setifpriority(const char *id, int param) 5694{ 5695 const char *errmsg = NULL; 5696 int prio; 5697 5698 prio = strtonum(id, 0, 15, &errmsg); 5699 if (errmsg) 5700 errx(1, "priority %s: %s", id, errmsg); 5701 5702 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 5703 ifr.ifr_metric = prio; 5704 if (ioctl(sock, SIOCSIFPRIORITY, (caddr_t)&ifr) == -1) 5705 warn("SIOCSIFPRIORITY"); 5706} 5707 5708/* 5709 * WireGuard configuration 5710 * 5711 * WG_BASE64_KEY_LEN specifies the size of a base64 encoded WireGuard key. 5712 * WG_TMP_KEY_LEN specifies the size of a decoded base64 key. For every 4 5713 * input (base64) bytes, 3 output bytes wil be produced. The output will be 5714 * padded with 0 bits, therefore we need more than the regular 32 bytes of 5715 * space. 5716 */ 5717#define WG_BASE64_KEY_LEN (4 * ((WG_KEY_LEN + 2) / 3)) 5718#define WG_LOAD_KEY(dst, src, fn_name) do { \ 5719 uint8_t _tmp[WG_KEY_LEN]; int _r; \ 5720 if (strlen(src) != WG_BASE64_KEY_LEN) \ 5721 errx(1, fn_name " (key): invalid length"); \ 5722 if ((_r = b64_pton(src, _tmp, sizeof(_tmp))) != sizeof(_tmp)) \ 5723 errx(1, fn_name " (key): invalid base64 %d/%zu", _r, sizeof(_tmp)); \ 5724 memcpy(dst, _tmp, WG_KEY_LEN); \ 5725} while (0) 5726 5727struct wg_data_io wgdata = { 0 }; 5728struct wg_interface_io *wg_interface = NULL; 5729struct wg_peer_io *wg_peer = NULL; 5730struct wg_aip_io *wg_aip = NULL; 5731 5732void 5733ensurewginterface(void) 5734{ 5735 if (wg_interface != NULL) 5736 return; 5737 wgdata.wgd_size = sizeof(*wg_interface); 5738 wgdata.wgd_interface = wg_interface = calloc(1, wgdata.wgd_size); 5739 if (wg_interface == NULL) 5740 err(1, "calloc"); 5741} 5742 5743void 5744growwgdata(size_t by) 5745{ 5746 ptrdiff_t peer_offset, aip_offset; 5747 5748 if (wg_interface == NULL) 5749 wgdata.wgd_size = sizeof(*wg_interface); 5750 5751 peer_offset = (void *)wg_peer - (void *)wg_interface; 5752 aip_offset = (void *)wg_aip - (void *)wg_interface; 5753 5754 wgdata.wgd_size += by; 5755 wgdata.wgd_interface = realloc(wg_interface, wgdata.wgd_size); 5756 if (wgdata.wgd_interface == NULL) 5757 err(1, "calloc"); 5758 if (wg_interface == NULL) 5759 bzero(wgdata.wgd_interface, sizeof(*wg_interface)); 5760 wg_interface = wgdata.wgd_interface; 5761 5762 if (wg_peer != NULL) 5763 wg_peer = (void *)wg_interface + peer_offset; 5764 if (wg_aip != NULL) 5765 wg_aip = (void *)wg_interface + aip_offset; 5766 5767 bzero((char *)wg_interface + wgdata.wgd_size - by, by); 5768} 5769 5770void 5771setwgpeer(const char *peerkey_b64, int param) 5772{ 5773 growwgdata(sizeof(*wg_peer)); 5774 if (wg_aip) 5775 wg_peer = (struct wg_peer_io *)wg_aip; 5776 else 5777 wg_peer = &wg_interface->i_peers[0]; 5778 wg_aip = &wg_peer->p_aips[0]; 5779 wg_peer->p_flags |= WG_PEER_HAS_PUBLIC; 5780 WG_LOAD_KEY(wg_peer->p_public, peerkey_b64, "wgpeer"); 5781 wg_interface->i_peers_count++; 5782} 5783 5784void 5785setwgpeerdesc(const char *descr, int param) 5786{ 5787 if (wg_peer == NULL) 5788 errx(1, "wgdescr: wgpeer not set"); 5789 wg_peer->p_flags |= WG_PEER_SET_DESCRIPTION; 5790 strlcpy(wg_peer->p_description, descr, IFDESCRSIZE); 5791} 5792 5793void 5794setwgpeeraip(const char *aip, int param) 5795{ 5796 int res; 5797 if (wg_peer == NULL) 5798 errx(1, "wgaip: wgpeer not set"); 5799 5800 growwgdata(sizeof(*wg_aip)); 5801 5802 if ((res = inet_net_pton(AF_INET, aip, &wg_aip->a_ipv4, 5803 sizeof(wg_aip->a_ipv4))) != -1) { 5804 wg_aip->a_af = AF_INET; 5805 } else if ((res = inet_net_pton(AF_INET6, aip, &wg_aip->a_ipv6, 5806 sizeof(wg_aip->a_ipv6))) != -1) { 5807 wg_aip->a_af = AF_INET6; 5808 } else { 5809 errx(1, "wgaip: bad address"); 5810 } 5811 5812 wg_aip->a_cidr = res; 5813 5814 wg_peer->p_flags |= WG_PEER_REPLACE_AIPS; 5815 wg_peer->p_aips_count++; 5816 5817 wg_aip++; 5818} 5819 5820void 5821setwgpeerep(const char *host, const char *service) 5822{ 5823 int error; 5824 struct addrinfo *ai; 5825 5826 if (wg_peer == NULL) 5827 errx(1, "wgendpoint: wgpeer not set"); 5828 5829 if ((error = getaddrinfo(host, service, NULL, &ai)) != 0) 5830 errx(1, "%s", gai_strerror(error)); 5831 5832 wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT; 5833 memcpy(&wg_peer->p_sa, ai->ai_addr, ai->ai_addrlen); 5834 freeaddrinfo(ai); 5835} 5836 5837void 5838setwgpeerpsk(const char *psk_b64, int param) 5839{ 5840 if (wg_peer == NULL) 5841 errx(1, "wgpsk: wgpeer not set"); 5842 wg_peer->p_flags |= WG_PEER_HAS_PSK; 5843 WG_LOAD_KEY(wg_peer->p_psk, psk_b64, "wgpsk"); 5844} 5845 5846void 5847setwgpeerpka(const char *pka, int param) 5848{ 5849 const char *errmsg = NULL; 5850 if (wg_peer == NULL) 5851 errx(1, "wgpka: wgpeer not set"); 5852 /* 43200 == 12h, reasonable for a 16 bit value */ 5853 wg_peer->p_flags |= WG_PEER_HAS_PKA; 5854 wg_peer->p_pka = strtonum(pka, 0, 43200, &errmsg); 5855 if (errmsg) 5856 errx(1, "wgpka: %s, %s", pka, errmsg); 5857} 5858 5859void 5860setwgport(const char *port, int param) 5861{ 5862 const char *errmsg = NULL; 5863 ensurewginterface(); 5864 wg_interface->i_flags |= WG_INTERFACE_HAS_PORT; 5865 wg_interface->i_port = strtonum(port, 0, 65535, &errmsg); 5866 if (errmsg) 5867 errx(1, "wgport: %s, %s", port, errmsg); 5868} 5869 5870void 5871setwgkey(const char *private_b64, int param) 5872{ 5873 ensurewginterface(); 5874 wg_interface->i_flags |= WG_INTERFACE_HAS_PRIVATE; 5875 WG_LOAD_KEY(wg_interface->i_private, private_b64, "wgkey"); 5876} 5877 5878void 5879setwgrtable(const char *id, int param) 5880{ 5881 const char *errmsg = NULL; 5882 ensurewginterface(); 5883 wg_interface->i_flags |= WG_INTERFACE_HAS_RTABLE; 5884 wg_interface->i_rtable = strtonum(id, 0, RT_TABLEID_MAX, &errmsg); 5885 if (errmsg) 5886 errx(1, "wgrtable %s: %s", id, errmsg); 5887} 5888 5889void 5890unsetwgpeer(const char *peerkey_b64, int param) 5891{ 5892 setwgpeer(peerkey_b64, param); 5893 wg_peer->p_flags |= WG_PEER_REMOVE; 5894} 5895 5896void 5897unsetwgpeerdesc(const char *descr, int param) 5898{ 5899 if (wg_peer == NULL) 5900 errx(1, "wgdescr: wgpeer not set"); 5901 wg_peer->p_flags |= WG_PEER_SET_DESCRIPTION; 5902 strlcpy(wg_peer->p_description, "", IFDESCRSIZE); 5903} 5904 5905void 5906unsetwgpeerpsk(const char *value, int param) 5907{ 5908 if (wg_peer == NULL) 5909 errx(1, "wgpsk: wgpeer not set"); 5910 wg_peer->p_flags |= WG_PEER_HAS_PSK; 5911 bzero(wg_peer->p_psk, WG_KEY_LEN); 5912} 5913 5914void 5915unsetwgpeerall(const char *value, int param) 5916{ 5917 ensurewginterface(); 5918 wg_interface->i_flags |= WG_INTERFACE_REPLACE_PEERS; 5919} 5920 5921void 5922process_wg_commands(void) 5923{ 5924 if (actions & A_WIREGUARD) { 5925 strlcpy(wgdata.wgd_name, ifname, sizeof(wgdata.wgd_name)); 5926 5927 if (ioctl(sock, SIOCSWG, (caddr_t)&wgdata) == -1) 5928 err(1, "%s: SIOCSWG", wgdata.wgd_name); 5929 } 5930} 5931 5932void 5933wg_status(int ifaliases) 5934{ 5935 size_t i, j, last_size; 5936 struct timespec now; 5937 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 5938 char key[WG_BASE64_KEY_LEN + 1]; 5939 5940 strlcpy(wgdata.wgd_name, ifname, sizeof(wgdata.wgd_name)); 5941 wgdata.wgd_size = 0; 5942 wgdata.wgd_interface = NULL; 5943 for (last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) { 5944 if (ioctl(sock, SIOCGWG, (caddr_t)&wgdata) < 0) { 5945 if (errno == ENOTTY) 5946 goto out; 5947 err(1, "%s: SIOCGWG", wgdata.wgd_name); 5948 } 5949 if (last_size >= wgdata.wgd_size) 5950 break; 5951 wgdata.wgd_interface = realloc(wgdata.wgd_interface, 5952 wgdata.wgd_size); 5953 if (!wgdata.wgd_interface) 5954 err(1, "realloc"); 5955 } 5956 wg_interface = wgdata.wgd_interface; 5957 5958 if (wg_interface->i_flags & WG_INTERFACE_HAS_PORT) 5959 printf("\twgport %hu\n", wg_interface->i_port); 5960 if (wg_interface->i_flags & WG_INTERFACE_HAS_RTABLE) 5961 printf("\twgrtable %d\n", wg_interface->i_rtable); 5962 if (wg_interface->i_flags & WG_INTERFACE_HAS_PUBLIC) { 5963 b64_ntop(wg_interface->i_public, WG_KEY_LEN, 5964 key, sizeof(key)); 5965 printf("\twgpubkey %s\n", key); 5966 } 5967 5968 if (ifaliases) { 5969 wg_peer = &wg_interface->i_peers[0]; 5970 for (i = 0; i < wg_interface->i_peers_count; i++) { 5971 b64_ntop(wg_peer->p_public, WG_KEY_LEN, 5972 key, sizeof(key)); 5973 printf("\twgpeer %s\n", key); 5974 5975 if (strlen(wg_peer->p_description)) 5976 printf("\t\twgdescr: %s\n", 5977 wg_peer->p_description); 5978 5979 if (wg_peer->p_flags & WG_PEER_HAS_PSK) 5980 printf("\t\twgpsk (present)\n"); 5981 5982 if (wg_peer->p_flags & WG_PEER_HAS_PKA && wg_peer->p_pka) 5983 printf("\t\twgpka %u (sec)\n", wg_peer->p_pka); 5984 5985 if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT) { 5986 if (getnameinfo(&wg_peer->p_sa, wg_peer->p_sa.sa_len, 5987 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), 5988 NI_NUMERICHOST | NI_NUMERICSERV) == 0) 5989 printf("\t\twgendpoint %s %s\n", hbuf, sbuf); 5990 else 5991 printf("\t\twgendpoint unable to print\n"); 5992 } 5993 5994 printf("\t\ttx: %llu, rx: %llu\n", 5995 wg_peer->p_txbytes, wg_peer->p_rxbytes); 5996 5997 if (wg_peer->p_last_handshake.tv_sec != 0) { 5998 clock_gettime(CLOCK_REALTIME, &now); 5999 printf("\t\tlast handshake: %lld seconds ago\n", 6000 now.tv_sec - wg_peer->p_last_handshake.tv_sec); 6001 } 6002 6003 6004 wg_aip = &wg_peer->p_aips[0]; 6005 for (j = 0; j < wg_peer->p_aips_count; j++) { 6006 inet_ntop(wg_aip->a_af, &wg_aip->a_addr, 6007 hbuf, sizeof(hbuf)); 6008 printf("\t\twgaip %s/%d\n", hbuf, wg_aip->a_cidr); 6009 wg_aip++; 6010 } 6011 wg_peer = (struct wg_peer_io *)wg_aip; 6012 } 6013 } 6014out: 6015 free(wgdata.wgd_interface); 6016} 6017 6018const struct umb_valdescr umb_regstate[] = MBIM_REGSTATE_DESCRIPTIONS; 6019const struct umb_valdescr umb_dataclass[] = MBIM_DATACLASS_DESCRIPTIONS; 6020const struct umb_valdescr umb_simstate[] = MBIM_SIMSTATE_DESCRIPTIONS; 6021const struct umb_valdescr umb_istate[] = UMB_INTERNAL_STATE_DESCRIPTIONS; 6022 6023const struct umb_valdescr umb_classalias[] = { 6024 { MBIM_DATACLASS_GPRS | MBIM_DATACLASS_EDGE, "2g" }, 6025 { MBIM_DATACLASS_UMTS | MBIM_DATACLASS_HSDPA | MBIM_DATACLASS_HSUPA, 6026 "3g" }, 6027 { MBIM_DATACLASS_LTE, "4g" }, 6028 { 0, NULL } 6029}; 6030 6031static int 6032umb_descr2val(const struct umb_valdescr *vdp, char *str) 6033{ 6034 while (vdp->descr != NULL) { 6035 if (!strcasecmp(vdp->descr, str)) 6036 return vdp->val; 6037 vdp++; 6038 } 6039 return 0; 6040} 6041 6042void 6043umb_status(void) 6044{ 6045 struct umb_info mi; 6046 char provider[UMB_PROVIDERNAME_MAXLEN+1]; 6047 char providerid[UMB_PROVIDERID_MAXLEN+1]; 6048 char roamingtxt[UMB_ROAMINGTEXT_MAXLEN+1]; 6049 char devid[UMB_DEVID_MAXLEN+1]; 6050 char fwinfo[UMB_FWINFO_MAXLEN+1]; 6051 char hwinfo[UMB_HWINFO_MAXLEN+1]; 6052 char sid[UMB_SUBSCRIBERID_MAXLEN+1]; 6053 char iccid[UMB_ICCID_MAXLEN+1]; 6054 char apn[UMB_APN_MAXLEN+1]; 6055 char pn[UMB_PHONENR_MAXLEN+1]; 6056 int i, n; 6057 char astr[INET6_ADDRSTRLEN]; 6058 6059 memset((char *)&mi, 0, sizeof(mi)); 6060 ifr.ifr_data = (caddr_t)&mi; 6061 if (ioctl(sock, SIOCGUMBINFO, (caddr_t)&ifr) == -1) 6062 return; 6063 6064 if (mi.nwerror) { 6065 /* 3GPP 24.008 Cause Code */ 6066 printf("\terror: "); 6067 switch (mi.nwerror) { 6068 case 2: 6069 printf("SIM not activated"); 6070 break; 6071 case 4: 6072 printf("Roaming not supported"); 6073 break; 6074 case 6: 6075 printf("SIM reported stolen"); 6076 break; 6077 case 7: 6078 printf("No GPRS subscription"); 6079 break; 6080 case 8: 6081 printf("GPRS and non-GPRS services not allowed"); 6082 break; 6083 case 11: 6084 printf("Subscription expired"); 6085 break; 6086 case 12: 6087 printf("Subscription does not cover current location"); 6088 break; 6089 case 13: 6090 printf("No roaming in this location"); 6091 break; 6092 case 14: 6093 printf("GPRS not supported"); 6094 break; 6095 case 15: 6096 printf("No subscription for the service"); 6097 break; 6098 case 17: 6099 printf("Registration failed"); 6100 break; 6101 case 22: 6102 printf("Network congestion"); 6103 break; 6104 default: 6105 printf("Error code %d", mi.nwerror); 6106 break; 6107 } 6108 printf("\n"); 6109 } 6110 6111 printf("\troaming %s registration %s", 6112 mi.enable_roaming ? "enabled" : "disabled", 6113 umb_val2descr(umb_regstate, mi.regstate)); 6114 utf16_to_char(mi.roamingtxt, UMB_ROAMINGTEXT_MAXLEN, 6115 roamingtxt, sizeof (roamingtxt)); 6116 if (roamingtxt[0]) 6117 printf(" [%s]", roamingtxt); 6118 printf("\n"); 6119 6120 if (showclasses) 6121 umb_printclasses("available classes", mi.supportedclasses); 6122 printf("\tstate %s cell-class %s", 6123 umb_val2descr(umb_istate, mi.state), 6124 umb_val2descr(umb_dataclass, mi.highestclass)); 6125 if (mi.rssi != UMB_VALUE_UNKNOWN && mi.rssi != 0) 6126 printf(" rssi %ddBm", mi.rssi); 6127 if (mi.uplink_speed != 0 || mi.downlink_speed != 0) { 6128 char s[2][FMT_SCALED_STRSIZE]; 6129 if (fmt_scaled(mi.uplink_speed, s[0]) != 0) 6130 snprintf(s[0], sizeof (s[0]), "%llu", mi.uplink_speed); 6131 if (fmt_scaled(mi.downlink_speed, s[1]) != 0) 6132 snprintf(s[1], sizeof (s[1]), "%llu", mi.downlink_speed); 6133 printf(" speed %sbps up %sbps down", s[0], s[1]); 6134 } 6135 printf("\n"); 6136 6137 printf("\tSIM %s PIN ", umb_val2descr(umb_simstate, mi.sim_state)); 6138 switch (mi.pin_state) { 6139 case UMB_PIN_REQUIRED: 6140 printf("required"); 6141 break; 6142 case UMB_PIN_UNLOCKED: 6143 printf("valid"); 6144 break; 6145 case UMB_PUK_REQUIRED: 6146 printf("locked (PUK required)"); 6147 break; 6148 default: 6149 printf("unknown state (%d)", mi.pin_state); 6150 break; 6151 } 6152 if (mi.pin_attempts_left != UMB_VALUE_UNKNOWN) 6153 printf(" (%d attempts left)", mi.pin_attempts_left); 6154 printf("\n"); 6155 6156 utf16_to_char(mi.sid, UMB_SUBSCRIBERID_MAXLEN, sid, sizeof (sid)); 6157 utf16_to_char(mi.iccid, UMB_ICCID_MAXLEN, iccid, sizeof (iccid)); 6158 utf16_to_char(mi.provider, UMB_PROVIDERNAME_MAXLEN, 6159 provider, sizeof (provider)); 6160 utf16_to_char(mi.providerid, UMB_PROVIDERID_MAXLEN, 6161 providerid, sizeof (providerid)); 6162 if (sid[0] || iccid[0]) { 6163 printf("\t"); 6164 n = 0; 6165 if (sid[0]) 6166 printf("%ssubscriber-id %s", n++ ? " " : "", sid); 6167 if (iccid[0]) 6168 printf("%sICC-id %s", n++ ? " " : "", iccid); 6169 printf("\n"); 6170 } 6171 6172 utf16_to_char(mi.hwinfo, UMB_HWINFO_MAXLEN, hwinfo, sizeof (hwinfo)); 6173 utf16_to_char(mi.devid, UMB_DEVID_MAXLEN, devid, sizeof (devid)); 6174 utf16_to_char(mi.fwinfo, UMB_FWINFO_MAXLEN, fwinfo, sizeof (fwinfo)); 6175 if (hwinfo[0] || devid[0] || fwinfo[0]) { 6176 printf("\t"); 6177 n = 0; 6178 if (hwinfo[0]) 6179 printf("%sdevice %s", n++ ? " " : "", hwinfo); 6180 if (devid[0]) { 6181 printf("%s", n++ ? " " : ""); 6182 switch (mi.cellclass) { 6183 case MBIM_CELLCLASS_GSM: 6184 printf("IMEI"); 6185 break; 6186 case MBIM_CELLCLASS_CDMA: 6187 n = strlen(devid); 6188 if (n == 8 || n == 11) { 6189 printf("ESN"); 6190 break; 6191 } else if (n == 14 || n == 18) { 6192 printf("MEID"); 6193 break; 6194 } 6195 /*FALLTHROUGH*/ 6196 default: 6197 printf("ID"); 6198 break; 6199 } 6200 printf(" %s", devid); 6201 } 6202 if (fwinfo[0]) 6203 printf("%sfirmware %s", n++ ? " " : "", fwinfo); 6204 printf("\n"); 6205 } 6206 6207 utf16_to_char(mi.pn, UMB_PHONENR_MAXLEN, pn, sizeof (pn)); 6208 utf16_to_char(mi.apn, UMB_APN_MAXLEN, apn, sizeof (apn)); 6209 if (pn[0] || apn[0] || provider[0] || providerid[0]) { 6210 printf("\t"); 6211 n = 0; 6212 if (pn[0]) 6213 printf("%sphone# %s", n++ ? " " : "", pn); 6214 if (apn[0]) 6215 printf("%sAPN %s", n++ ? " " : "", apn); 6216 if (provider[0]) 6217 printf("%sprovider %s", n++ ? " " : "", provider); 6218 if (providerid[0]) 6219 printf("%sprovider-id %s", n ? " " : "", providerid); 6220 printf("\n"); 6221 } 6222 6223 for (i = 0, n = 0; i < UMB_MAX_DNSSRV; i++) { 6224 if (mi.ipv4dns[i].s_addr == INADDR_ANY) 6225 break; 6226 printf("%s %s", n++ ? "" : "\tdns", 6227 inet_ntop(AF_INET, &mi.ipv4dns[i], astr, sizeof(astr))); 6228 } 6229 for (i = 0; i < UMB_MAX_DNSSRV; i++) { 6230 if (memcmp(&mi.ipv6dns[i], &in6addr_any, 6231 sizeof (mi.ipv6dns[i])) == 0) 6232 break; 6233 printf("%s %s", n++ ? "" : "\tdns", 6234 inet_ntop(AF_INET6, &mi.ipv6dns[i], astr, sizeof(astr))); 6235 } 6236 if (n) 6237 printf("\n"); 6238} 6239 6240void 6241umb_printclasses(char *tag, int c) 6242{ 6243 int i; 6244 char *sep = ""; 6245 6246 printf("\t%s: ", tag); 6247 i = 0; 6248 while (umb_dataclass[i].descr) { 6249 if (umb_dataclass[i].val & c) { 6250 printf("%s%s", sep, umb_dataclass[i].descr); 6251 sep = ","; 6252 } 6253 i++; 6254 } 6255 printf("\n"); 6256} 6257 6258int 6259umb_parse_classes(const char *spec) 6260{ 6261 char *optlist, *str; 6262 int c = 0, v; 6263 6264 if ((optlist = strdup(spec)) == NULL) 6265 err(1, "strdup"); 6266 str = strtok(optlist, ","); 6267 while (str != NULL) { 6268 if ((v = umb_descr2val(umb_dataclass, str)) != 0 || 6269 (v = umb_descr2val(umb_classalias, str)) != 0) 6270 c |= v; 6271 str = strtok(NULL, ","); 6272 } 6273 free(optlist); 6274 return c; 6275} 6276 6277void 6278umb_setpin(const char *pin, int d) 6279{ 6280 umb_pinop(MBIM_PIN_OP_ENTER, 0, pin, NULL); 6281} 6282 6283void 6284umb_chgpin(const char *pin, const char *newpin) 6285{ 6286 umb_pinop(MBIM_PIN_OP_CHANGE, 0, pin, newpin); 6287} 6288 6289void 6290umb_puk(const char *pin, const char *newpin) 6291{ 6292 umb_pinop(MBIM_PIN_OP_ENTER, 1, pin, newpin); 6293} 6294 6295void 6296umb_pinop(int op, int is_puk, const char *pin, const char *newpin) 6297{ 6298 struct umb_parameter mp; 6299 6300 memset(&mp, 0, sizeof (mp)); 6301 ifr.ifr_data = (caddr_t)∓ 6302 if (ioctl(sock, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) 6303 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); 6304 6305 mp.op = op; 6306 mp.is_puk = is_puk; 6307 if ((mp.pinlen = char_to_utf16(pin, (uint16_t *)mp.pin, 6308 sizeof (mp.pin))) == -1) 6309 errx(1, "PIN too long"); 6310 6311 if (newpin) { 6312 if ((mp.newpinlen = char_to_utf16(newpin, (uint16_t *)mp.newpin, 6313 sizeof (mp.newpin))) == -1) 6314 errx(1, "new PIN too long"); 6315 } 6316 6317 if (ioctl(sock, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) 6318 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); 6319} 6320 6321void 6322umb_apn(const char *apn, int d) 6323{ 6324 struct umb_parameter mp; 6325 6326 memset(&mp, 0, sizeof (mp)); 6327 ifr.ifr_data = (caddr_t)∓ 6328 if (ioctl(sock, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) 6329 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); 6330 6331 if (d != 0) 6332 memset(mp.apn, 0, sizeof (mp.apn)); 6333 else if ((mp.apnlen = char_to_utf16(apn, mp.apn, 6334 sizeof (mp.apn))) == -1) 6335 errx(1, "APN too long"); 6336 6337 if (ioctl(sock, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) 6338 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); 6339} 6340 6341void 6342umb_setclass(const char *val, int d) 6343{ 6344 struct umb_parameter mp; 6345 6346 if (val == NULL) { 6347 if (showclasses) 6348 usage(); 6349 showclasses = 1; 6350 return; 6351 } 6352 6353 memset(&mp, 0, sizeof (mp)); 6354 ifr.ifr_data = (caddr_t)∓ 6355 if (ioctl(sock, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) 6356 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); 6357 if (d != -1) 6358 mp.preferredclasses = umb_parse_classes(val); 6359 else 6360 mp.preferredclasses = MBIM_DATACLASS_NONE; 6361 if (ioctl(sock, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) 6362 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); 6363} 6364 6365void 6366umb_roaming(const char *val, int d) 6367{ 6368 struct umb_parameter mp; 6369 6370 memset(&mp, 0, sizeof (mp)); 6371 ifr.ifr_data = (caddr_t)∓ 6372 if (ioctl(sock, SIOCGUMBPARAM, (caddr_t)&ifr) == -1) 6373 err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); 6374 mp.roaming = d; 6375 if (ioctl(sock, SIOCSUMBPARAM, (caddr_t)&ifr) == -1) 6376 err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); 6377} 6378 6379void 6380utf16_to_char(uint16_t *in, int inlen, char *out, size_t outlen) 6381{ 6382 uint16_t c; 6383 6384 while (outlen > 0) { 6385 c = inlen > 0 ? letoh16(*in) : 0; 6386 if (c == 0 || --outlen == 0) { 6387 /* always NUL terminate result */ 6388 *out = '\0'; 6389 break; 6390 } 6391 *out++ = isascii(c) ? (char)c : '?'; 6392 in++; 6393 inlen--; 6394 } 6395} 6396 6397int 6398char_to_utf16(const char *in, uint16_t *out, size_t outlen) 6399{ 6400 int n = 0; 6401 uint16_t c; 6402 6403 for (;;) { 6404 c = *in++; 6405 6406 if (c == '\0') { 6407 /* 6408 * NUL termination is not required, but zero out the 6409 * residual buffer 6410 */ 6411 memset(out, 0, outlen); 6412 return n; 6413 } 6414 if (outlen < sizeof (*out)) 6415 return -1; 6416 6417 *out++ = htole16(c); 6418 n += sizeof (*out); 6419 outlen -= sizeof (*out); 6420 } 6421} 6422 6423#endif 6424 6425#define SIN(x) ((struct sockaddr_in *) &(x)) 6426struct sockaddr_in *sintab[] = { 6427SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr), 6428SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)}; 6429 6430void 6431in_getaddr(const char *s, int which) 6432{ 6433 struct sockaddr_in *sin = sintab[which], tsin; 6434 struct hostent *hp; 6435 int bits, l; 6436 char p[3]; 6437 6438 bzero(&tsin, sizeof(tsin)); 6439 sin->sin_len = sizeof(*sin); 6440 if (which != MASK) 6441 sin->sin_family = AF_INET; 6442 6443 if (which == ADDR && strrchr(s, '/') != NULL && 6444 (bits = inet_net_pton(AF_INET, s, &tsin.sin_addr, 6445 sizeof(tsin.sin_addr))) != -1) { 6446 l = snprintf(p, sizeof(p), "%d", bits); 6447 if (l < 0 || l >= sizeof(p)) 6448 errx(1, "%d: bad prefixlen", bits); 6449 in_getprefix(p, MASK); 6450 memcpy(&sin->sin_addr, &tsin.sin_addr, sizeof(sin->sin_addr)); 6451 } else if (inet_aton(s, &sin->sin_addr) == 0) { 6452 if ((hp = gethostbyname(s))) 6453 memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); 6454 else 6455 errx(1, "%s: bad value", s); 6456 } 6457 if (which == MASK && (ntohl(sin->sin_addr.s_addr) & 6458 (~ntohl(sin->sin_addr.s_addr) >> 1))) 6459 errx(1, "%s: non-contiguous mask", s); 6460} 6461 6462void 6463in_getprefix(const char *plen, int which) 6464{ 6465 struct sockaddr_in *sin = sintab[which]; 6466 const char *errmsg = NULL; 6467 u_char *cp; 6468 int len; 6469 6470 len = strtonum(plen, 0, 32, &errmsg); 6471 if (errmsg) 6472 errx(1, "prefix %s: %s", plen, errmsg); 6473 6474 sin->sin_len = sizeof(*sin); 6475 if (which != MASK) 6476 sin->sin_family = AF_INET; 6477 if ((len == 0) || (len == 32)) { 6478 memset(&sin->sin_addr, 0xff, sizeof(struct in_addr)); 6479 return; 6480 } 6481 memset((void *)&sin->sin_addr, 0x00, sizeof(sin->sin_addr)); 6482 for (cp = (u_char *)&sin->sin_addr; len > 7; len -= 8) 6483 *cp++ = 0xff; 6484 if (len) 6485 *cp = 0xff << (8 - len); 6486} 6487 6488/* 6489 * Print a value a la the %b format of the kernel's printf 6490 */ 6491void 6492printb(char *s, unsigned int v, unsigned char *bits) 6493{ 6494 int i, any = 0; 6495 unsigned char c; 6496 6497 if (bits && *bits == 8) 6498 printf("%s=%o", s, v); 6499 else 6500 printf("%s=%x", s, v); 6501 6502 if (bits) { 6503 bits++; 6504 putchar('<'); 6505 while ((i = *bits++)) { 6506 if (v & (1 << (i-1))) { 6507 if (any) 6508 putchar(','); 6509 any = 1; 6510 for (; (c = *bits) > 32; bits++) 6511 putchar(c); 6512 } else 6513 for (; *bits > 32; bits++) 6514 ; 6515 } 6516 putchar('>'); 6517 } 6518} 6519 6520/* 6521 * A simple version of printb for status output 6522 */ 6523void 6524printb_status(unsigned short v, unsigned char *bits) 6525{ 6526 int i, any = 0; 6527 unsigned char c; 6528 6529 if (bits) { 6530 bits++; 6531 while ((i = *bits++)) { 6532 if (v & (1 << (i-1))) { 6533 if (any) 6534 putchar(','); 6535 any = 1; 6536 for (; (c = *bits) > 32; bits++) 6537 putchar(tolower(c)); 6538 } else 6539 for (; *bits > 32; bits++) 6540 ; 6541 } 6542 } 6543} 6544 6545#define SIN6(x) ((struct sockaddr_in6 *) &(x)) 6546struct sockaddr_in6 *sin6tab[] = { 6547SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr), 6548SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)}; 6549 6550void 6551in6_getaddr(const char *s, int which) 6552{ 6553 struct sockaddr_in6 *sin6 = sin6tab[which]; 6554 struct addrinfo hints, *res; 6555 char buf[HOST_NAME_MAX+1 + sizeof("/128")], *pfxlen; 6556 int error; 6557 6558 memset(&hints, 0, sizeof(hints)); 6559 hints.ai_family = AF_INET6; 6560 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 6561 6562 if (which == ADDR && strchr(s, '/') != NULL) { 6563 if (strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) 6564 errx(1, "%s: bad value", s); 6565 pfxlen = strchr(buf, '/'); 6566 *pfxlen++ = '\0'; 6567 s = buf; 6568 in6_getprefix(pfxlen, MASK); 6569 explicit_prefix = 1; 6570 } 6571 6572 error = getaddrinfo(s, "0", &hints, &res); 6573 if (error) 6574 errx(1, "%s: %s", s, gai_strerror(error)); 6575 memcpy(sin6, res->ai_addr, res->ai_addrlen); 6576#ifdef __KAME__ 6577 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 6578 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] == 0 && 6579 sin6->sin6_scope_id) { 6580 *(u_int16_t *)&sin6->sin6_addr.s6_addr[2] = 6581 htons(sin6->sin6_scope_id & 0xffff); 6582 sin6->sin6_scope_id = 0; 6583 } 6584#endif /* __KAME__ */ 6585 freeaddrinfo(res); 6586} 6587 6588void 6589in6_getprefix(const char *plen, int which) 6590{ 6591 struct sockaddr_in6 *sin6 = sin6tab[which]; 6592 const char *errmsg = NULL; 6593 u_char *cp; 6594 int len; 6595 6596 len = strtonum(plen, 0, 128, &errmsg); 6597 if (errmsg) 6598 errx(1, "prefix %s: %s", plen, errmsg); 6599 6600 sin6->sin6_len = sizeof(*sin6); 6601 if (which != MASK) 6602 sin6->sin6_family = AF_INET6; 6603 if ((len == 0) || (len == 128)) { 6604 memset(&sin6->sin6_addr, 0xff, sizeof(struct in6_addr)); 6605 return; 6606 } 6607 memset((void *)&sin6->sin6_addr, 0x00, sizeof(sin6->sin6_addr)); 6608 for (cp = (u_char *)&sin6->sin6_addr; len > 7; len -= 8) 6609 *cp++ = 0xff; 6610 if (len) 6611 *cp = 0xff << (8 - len); 6612} 6613 6614int 6615prefix(void *val, int size) 6616{ 6617 u_char *nam = (u_char *)val; 6618 int byte, bit, plen = 0; 6619 6620 for (byte = 0; byte < size; byte++, plen += 8) 6621 if (nam[byte] != 0xff) 6622 break; 6623 if (byte == size) 6624 return (plen); 6625 for (bit = 7; bit != 0; bit--, plen++) 6626 if (!(nam[byte] & (1 << bit))) 6627 break; 6628 for (; bit != 0; bit--) 6629 if (nam[byte] & (1 << bit)) 6630 return (0); 6631 byte++; 6632 for (; byte < size; byte++) 6633 if (nam[byte]) 6634 return (0); 6635 return (plen); 6636} 6637 6638/* Print usage and exit */ 6639__dead void 6640usage(void) 6641{ 6642 fprintf(stderr, 6643 "usage: ifconfig [-AaC] [-M lladdr] [interface] [address_family]\n" 6644 "\t\t[address [dest_address]] [parameters]\n"); 6645 exit(1); 6646} 6647 6648void 6649getifgroups(void) 6650{ 6651 int len, cnt; 6652 struct ifgroupreq ifgr; 6653 struct ifg_req *ifg; 6654 6655 memset(&ifgr, 0, sizeof(ifgr)); 6656 strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); 6657 6658 if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 6659 if (errno == EINVAL || errno == ENOTTY) 6660 return; 6661 else 6662 err(1, "%s: SIOCGIFGROUP", ifgr.ifgr_name); 6663 } 6664 6665 len = ifgr.ifgr_len; 6666 ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req), 6667 sizeof(struct ifg_req)); 6668 if (ifgr.ifgr_groups == NULL) 6669 err(1, "getifgroups"); 6670 if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 6671 err(1, "%s: SIOCGIFGROUP", ifgr.ifgr_name); 6672 6673 cnt = 0; 6674 ifg = ifgr.ifgr_groups; 6675 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 6676 len -= sizeof(struct ifg_req); 6677 if (strcmp(ifg->ifgrq_group, "all")) { 6678 if (cnt == 0) 6679 printf("\tgroups:"); 6680 cnt++; 6681 printf(" %s", ifg->ifgrq_group); 6682 } 6683 } 6684 if (cnt) 6685 printf("\n"); 6686 6687 free(ifgr.ifgr_groups); 6688} 6689 6690#ifndef SMALL 6691void 6692printifhwfeatures(const char *unused, int show) 6693{ 6694 struct if_data ifrdat; 6695 6696 if (!show) { 6697 if (showcapsflag) 6698 usage(); 6699 showcapsflag = 1; 6700 return; 6701 } 6702 bzero(&ifrdat, sizeof(ifrdat)); 6703 ifr.ifr_data = (caddr_t)&ifrdat; 6704 if (ioctl(sock, SIOCGIFDATA, (caddr_t)&ifr) == -1) 6705 err(1, "%s: SIOCGIFDATA", ifr.ifr_name); 6706 printb("\thwfeatures", (u_int)ifrdat.ifi_capabilities, HWFEATURESBITS); 6707 6708 if (ioctl(sock, SIOCGIFHARDMTU, (caddr_t)&ifr) != -1) { 6709 if (ifr.ifr_hardmtu) 6710 printf(" hardmtu %u", ifr.ifr_hardmtu); 6711 } 6712 putchar('\n'); 6713} 6714#endif 6715 6716char * 6717sec2str(time_t total) 6718{ 6719 static char result[256]; 6720 char *p = result; 6721 char *end = &result[sizeof(result)]; 6722 6723 snprintf(p, end - p, "%lld", (long long)total); 6724 return (result); 6725} 6726 6727void 6728setiflladdr(const char *addr, int param) 6729{ 6730 struct ether_addr *eap, eabuf; 6731 6732 if (!strcmp(addr, "random")) { 6733 arc4random_buf(&eabuf, sizeof eabuf); 6734 /* Non-multicast and claim it is a hardware address */ 6735 eabuf.ether_addr_octet[0] &= 0xfc; 6736 eap = &eabuf; 6737 } else { 6738 eap = ether_aton(addr); 6739 if (eap == NULL) { 6740 warnx("malformed link-level address"); 6741 return; 6742 } 6743 } 6744 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 6745 ifr.ifr_addr.sa_len = ETHER_ADDR_LEN; 6746 ifr.ifr_addr.sa_family = AF_LINK; 6747 bcopy(eap, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN); 6748 if (ioctl(sock, SIOCSIFLLADDR, (caddr_t)&ifr) == -1) 6749 warn("SIOCSIFLLADDR"); 6750} 6751 6752#ifndef SMALL 6753void 6754setrdomain(const char *id, int param) 6755{ 6756 const char *errmsg = NULL; 6757 int rdomainid; 6758 6759 rdomainid = strtonum(id, 0, RT_TABLEID_MAX, &errmsg); 6760 if (errmsg) 6761 errx(1, "rdomain %s: %s", id, errmsg); 6762 6763 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 6764 ifr.ifr_rdomainid = rdomainid; 6765 if (ioctl(sock, SIOCSIFRDOMAIN, (caddr_t)&ifr) == -1) 6766 warn("SIOCSIFRDOMAIN"); 6767} 6768 6769void 6770unsetrdomain(const char *ignored, int alsoignored) 6771{ 6772 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 6773 ifr.ifr_rdomainid = 0; 6774 if (ioctl(sock, SIOCSIFRDOMAIN, (caddr_t)&ifr) == -1) 6775 warn("SIOCSIFRDOMAIN"); 6776} 6777#endif 6778 6779#ifndef SMALL 6780void 6781setpair(const char *val, int d) 6782{ 6783 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 6784 if ((ifr.ifr_index = if_nametoindex(val)) == 0) { 6785 errno = ENOENT; 6786 err(1, "patch %s", val); 6787 } 6788 if (ioctl(sock, SIOCSIFPAIR, (caddr_t)&ifr) == -1) 6789 warn("SIOCSIFPAIR"); 6790} 6791 6792void 6793unsetpair(const char *val, int d) 6794{ 6795 ifr.ifr_index = 0; 6796 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 6797 if (ioctl(sock, SIOCSIFPAIR, (caddr_t)&ifr) == -1) 6798 warn("SIOCSIFPAIR"); 6799} 6800#endif 6801 6802#ifdef SMALL 6803void 6804setignore(const char *id, int param) 6805{ 6806 /* just digest the command */ 6807} 6808#endif 6809 6810int 6811findmac(const char *mac) 6812{ 6813 struct ifaddrs *ifap, *ifa; 6814 const char *ifnam = NULL; 6815 struct if_clonereq *ifcr; 6816 int ret = 0; 6817 6818 ifcr = get_cloners(); 6819 if (getifaddrs(&ifap) != 0) 6820 err(1, "getifaddrs"); 6821 6822 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 6823 struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr; 6824 6825 if (sdl != NULL && sdl->sdl_alen && 6826 (sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_CARP)) { 6827 if (strcmp(ether_ntoa((struct ether_addr *)LLADDR(sdl)), 6828 mac) == 0) { 6829 char *cp, *nam = ifa->ifa_name; 6830 int idx, skip = 0; 6831 size_t len; 6832 6833 /* MACs on cloned devices are ignored */ 6834 for (len = 0; nam[len]; len++) 6835 if (isdigit((unsigned char)nam[len])) 6836 break; 6837 for (cp = ifcr->ifcr_buffer, idx = 0; 6838 idx < ifcr->ifcr_count; 6839 idx++, cp += IFNAMSIZ) { 6840 if (strncmp(nam, cp, len) == 0) { 6841 skip = 1; 6842 break; 6843 } 6844 } 6845 if (skip) 6846 continue; 6847 6848 if (ifnam) { /* same MAC on multiple ifp */ 6849 ret = 1; 6850 goto done; 6851 } 6852 ifnam = nam; 6853 } 6854 } 6855 } 6856 if (ifnam) 6857 printf("%s\n", ifnam); 6858done: 6859 free(ifcr->ifcr_buffer); 6860 freeifaddrs(ifap); 6861 return ret; 6862} 6863