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