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