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