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