1 1.251 ozaki /* $NetBSD: ifconfig.c,v 1.251 2024/08/20 08:18:24 ozaki-r Exp $ */ 2 1.24 thorpej 3 1.41 thorpej /*- 4 1.64 thorpej * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. 5 1.24 thorpej * All rights reserved. 6 1.24 thorpej * 7 1.41 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.41 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.41 thorpej * NASA Ames Research Center. 10 1.41 thorpej * 11 1.24 thorpej * Redistribution and use in source and binary forms, with or without 12 1.24 thorpej * modification, are permitted provided that the following conditions 13 1.24 thorpej * are met: 14 1.24 thorpej * 1. Redistributions of source code must retain the above copyright 15 1.24 thorpej * notice, this list of conditions and the following disclaimer. 16 1.24 thorpej * 2. Redistributions in binary form must reproduce the above copyright 17 1.24 thorpej * notice, this list of conditions and the following disclaimer in the 18 1.24 thorpej * documentation and/or other materials provided with the distribution. 19 1.24 thorpej * 20 1.41 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.41 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.41 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.41 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.41 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.41 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.41 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.41 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.41 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.41 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.41 thorpej * POSSIBILITY OF SUCH DAMAGE. 31 1.24 thorpej */ 32 1.19 cgd 33 1.1 cgd /* 34 1.13 mycroft * Copyright (c) 1983, 1993 35 1.13 mycroft * The Regents of the University of California. All rights reserved. 36 1.1 cgd * 37 1.1 cgd * Redistribution and use in source and binary forms, with or without 38 1.1 cgd * modification, are permitted provided that the following conditions 39 1.1 cgd * are met: 40 1.1 cgd * 1. Redistributions of source code must retain the above copyright 41 1.1 cgd * notice, this list of conditions and the following disclaimer. 42 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 43 1.1 cgd * notice, this list of conditions and the following disclaimer in the 44 1.1 cgd * documentation and/or other materials provided with the distribution. 45 1.138 agc * 3. Neither the name of the University nor the names of its contributors 46 1.1 cgd * may be used to endorse or promote products derived from this software 47 1.1 cgd * without specific prior written permission. 48 1.1 cgd * 49 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 1.1 cgd * SUCH DAMAGE. 60 1.1 cgd */ 61 1.1 cgd 62 1.39 lukem #include <sys/cdefs.h> 63 1.1 cgd #ifndef lint 64 1.212 lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1993\ 65 1.212 lukem The Regents of the University of California. All rights reserved."); 66 1.251 ozaki __RCSID("$NetBSD: ifconfig.c,v 1.251 2024/08/20 08:18:24 ozaki-r Exp $"); 67 1.1 cgd #endif /* not lint */ 68 1.1 cgd 69 1.1 cgd #include <sys/param.h> 70 1.208 dyoung #include <sys/queue.h> 71 1.1 cgd #include <sys/socket.h> 72 1.1 cgd #include <sys/ioctl.h> 73 1.1 cgd 74 1.1 cgd #include <net/if.h> 75 1.30 thorpej #include <net/if_dl.h> 76 1.24 thorpej #include <net/if_media.h> 77 1.62 chopps #include <net/if_ether.h> 78 1.166 thorpej #include <netinet/in.h> /* XXX */ 79 1.166 thorpej #include <netinet/in_var.h> /* XXX */ 80 1.227 mbalmer 81 1.13 mycroft #include <netdb.h> 82 1.1 cgd 83 1.1 cgd #include <sys/protosw.h> 84 1.1 cgd 85 1.187 dyoung #include <assert.h> 86 1.13 mycroft #include <ctype.h> 87 1.13 mycroft #include <err.h> 88 1.13 mycroft #include <errno.h> 89 1.185 dyoung #include <stdbool.h> 90 1.50 chopps #include <stddef.h> 91 1.1 cgd #include <stdio.h> 92 1.1 cgd #include <stdlib.h> 93 1.1 cgd #include <string.h> 94 1.13 mycroft #include <unistd.h> 95 1.78 itojun #include <ifaddrs.h> 96 1.130 christos #include <util.h> 97 1.1 cgd 98 1.156 thorpej #include "extern.h" 99 1.161 thorpej 100 1.208 dyoung #include "media.h" 101 1.187 dyoung #include "parse.h" 102 1.187 dyoung #include "env.h" 103 1.224 pooka #include "prog_ops.h" 104 1.153 yamt 105 1.232 roy #define WAIT_DAD 10000000 /* nanoseconds between each poll, 10ms */ 106 1.232 roy 107 1.236 roy static bool bflag, dflag, hflag, sflag, uflag, Wflag, wflag; 108 1.220 dyoung bool lflag, Nflag, vflag, zflag; 109 1.236 roy static long wflag_secs, Wflag_secs; 110 1.1 cgd 111 1.236 roy static char gflags[10 + 26 * 2 + 1] = "AabCdhlNsuvW:w:z"; 112 1.208 dyoung bool gflagset[10 + 26 * 2]; 113 1.187 dyoung 114 1.251 ozaki static int link_state(prop_dictionary_t); 115 1.251 ozaki static const char *link_state_str(int); 116 1.208 dyoung static int carrier(prop_dictionary_t); 117 1.208 dyoung static int clone_command(prop_dictionary_t, prop_dictionary_t); 118 1.208 dyoung static void do_setifpreference(prop_dictionary_t); 119 1.208 dyoung static int flag_index(int); 120 1.208 dyoung static void init_afs(void); 121 1.208 dyoung static int list_cloners(prop_dictionary_t, prop_dictionary_t); 122 1.208 dyoung static int media_status_exec(prop_dictionary_t, prop_dictionary_t); 123 1.232 roy static int wait_dad_exec(prop_dictionary_t, prop_dictionary_t); 124 1.187 dyoung static int no_cmds_exec(prop_dictionary_t, prop_dictionary_t); 125 1.208 dyoung static int notrailers(prop_dictionary_t, prop_dictionary_t); 126 1.208 dyoung static void printall(const char *, prop_dictionary_t); 127 1.208 dyoung static int setifaddr(prop_dictionary_t, prop_dictionary_t); 128 1.208 dyoung static int setifbroadaddr(prop_dictionary_t, prop_dictionary_t); 129 1.208 dyoung static int setifcaps(prop_dictionary_t, prop_dictionary_t); 130 1.208 dyoung static int setifdstormask(prop_dictionary_t, prop_dictionary_t); 131 1.208 dyoung static int setifflags(prop_dictionary_t, prop_dictionary_t); 132 1.208 dyoung static int setifmetric(prop_dictionary_t, prop_dictionary_t); 133 1.208 dyoung static int setifmtu(prop_dictionary_t, prop_dictionary_t); 134 1.208 dyoung static int setifnetmask(prop_dictionary_t, prop_dictionary_t); 135 1.208 dyoung static int setifprefixlen(prop_dictionary_t, prop_dictionary_t); 136 1.223 pooka static int setlinkstr(prop_dictionary_t, prop_dictionary_t); 137 1.223 pooka static int unsetlinkstr(prop_dictionary_t, prop_dictionary_t); 138 1.239 ozaki static int setifdescr(prop_dictionary_t, prop_dictionary_t); 139 1.239 ozaki static int unsetifdescr(prop_dictionary_t, prop_dictionary_t); 140 1.248 roy static void status(prop_dictionary_t, prop_dictionary_t); 141 1.226 joerg __dead static void usage(void); 142 1.187 dyoung 143 1.198 dyoung static const struct kwinst ifflagskw[] = { 144 1.215 plunky IFKW("arp", -IFF_NOARP) 145 1.187 dyoung , IFKW("debug", IFF_DEBUG) 146 1.249 knakahar , IFKW("unnumbered", IFF_UNNUMBERED) 147 1.187 dyoung , IFKW("link0", IFF_LINK0) 148 1.187 dyoung , IFKW("link1", IFF_LINK1) 149 1.187 dyoung , IFKW("link2", IFF_LINK2) 150 1.205 dyoung , {.k_word = "down", .k_type = KW_T_INT, .k_int = -IFF_UP} 151 1.205 dyoung , {.k_word = "up", .k_type = KW_T_INT, .k_int = IFF_UP} 152 1.187 dyoung }; 153 1.187 dyoung 154 1.198 dyoung static const struct kwinst ifcapskw[] = { 155 1.187 dyoung IFKW("ip4csum-tx", IFCAP_CSUM_IPv4_Tx) 156 1.187 dyoung , IFKW("ip4csum-rx", IFCAP_CSUM_IPv4_Rx) 157 1.187 dyoung , IFKW("tcp4csum-tx", IFCAP_CSUM_TCPv4_Tx) 158 1.187 dyoung , IFKW("tcp4csum-rx", IFCAP_CSUM_TCPv4_Rx) 159 1.187 dyoung , IFKW("udp4csum-tx", IFCAP_CSUM_UDPv4_Tx) 160 1.187 dyoung , IFKW("udp4csum-rx", IFCAP_CSUM_UDPv4_Rx) 161 1.187 dyoung , IFKW("tcp6csum-tx", IFCAP_CSUM_TCPv6_Tx) 162 1.187 dyoung , IFKW("tcp6csum-rx", IFCAP_CSUM_TCPv6_Rx) 163 1.187 dyoung , IFKW("udp6csum-tx", IFCAP_CSUM_UDPv6_Tx) 164 1.187 dyoung , IFKW("udp6csum-rx", IFCAP_CSUM_UDPv6_Rx) 165 1.187 dyoung , IFKW("ip4csum", IFCAP_CSUM_IPv4_Tx|IFCAP_CSUM_IPv4_Rx) 166 1.187 dyoung , IFKW("tcp4csum", IFCAP_CSUM_TCPv4_Tx|IFCAP_CSUM_TCPv4_Rx) 167 1.187 dyoung , IFKW("udp4csum", IFCAP_CSUM_UDPv4_Tx|IFCAP_CSUM_UDPv4_Rx) 168 1.187 dyoung , IFKW("tcp6csum", IFCAP_CSUM_TCPv6_Tx|IFCAP_CSUM_TCPv6_Rx) 169 1.187 dyoung , IFKW("udp6csum", IFCAP_CSUM_UDPv6_Tx|IFCAP_CSUM_UDPv6_Rx) 170 1.187 dyoung , IFKW("tso4", IFCAP_TSOv4) 171 1.187 dyoung , IFKW("tso6", IFCAP_TSOv6) 172 1.187 dyoung }; 173 1.45 thorpej 174 1.187 dyoung extern struct pbranch command_root; 175 1.187 dyoung extern struct pbranch opt_command; 176 1.187 dyoung extern struct pbranch opt_family, opt_silent_family; 177 1.200 dyoung extern struct pkw cloning, silent_family, family, ifcaps, ifflags, misc; 178 1.223 pooka extern struct pstr parse_linkstr; 179 1.187 dyoung 180 1.187 dyoung struct pinteger parse_metric = PINTEGER_INITIALIZER(&parse_metric, "metric", 10, 181 1.187 dyoung setifmetric, "metric", &command_root.pb_parser); 182 1.187 dyoung 183 1.187 dyoung struct pinteger parse_mtu = PINTEGER_INITIALIZER(&parse_mtu, "mtu", 10, 184 1.187 dyoung setifmtu, "mtu", &command_root.pb_parser); 185 1.187 dyoung 186 1.187 dyoung struct pinteger parse_prefixlen = PINTEGER_INITIALIZER(&parse_prefixlen, 187 1.187 dyoung "prefixlen", 10, setifprefixlen, "prefixlen", &command_root.pb_parser); 188 1.187 dyoung 189 1.187 dyoung struct pinteger parse_preference = PINTEGER_INITIALIZER1(&parse_preference, 190 1.187 dyoung "preference", INT16_MIN, INT16_MAX, 10, NULL, "preference", 191 1.187 dyoung &command_root.pb_parser); 192 1.187 dyoung 193 1.187 dyoung struct paddr parse_netmask = PADDR_INITIALIZER(&parse_netmask, "netmask", 194 1.187 dyoung setifnetmask, "dstormask", NULL, NULL, NULL, &command_root.pb_parser); 195 1.187 dyoung 196 1.187 dyoung struct paddr parse_broadcast = PADDR_INITIALIZER(&parse_broadcast, 197 1.187 dyoung "broadcast address", 198 1.187 dyoung setifbroadaddr, "broadcast", NULL, NULL, NULL, &command_root.pb_parser); 199 1.187 dyoung 200 1.239 ozaki struct pstr parse_descr = PSTR_INITIALIZER1(&parse_descr, "descr", 201 1.239 ozaki setifdescr, "descr", false, &command_root.pb_parser); 202 1.239 ozaki 203 1.198 dyoung static const struct kwinst misckw[] = { 204 1.208 dyoung {.k_word = "alias", .k_key = "alias", .k_deact = "alias", 205 1.187 dyoung .k_type = KW_T_BOOL, .k_neg = true, 206 1.187 dyoung .k_bool = true, .k_negbool = false, 207 1.208 dyoung .k_nextparser = &command_root.pb_parser} 208 1.187 dyoung , {.k_word = "broadcast", .k_nextparser = &parse_broadcast.pa_parser} 209 1.187 dyoung , {.k_word = "delete", .k_key = "alias", .k_deact = "alias", 210 1.208 dyoung .k_type = KW_T_BOOL, .k_bool = false, 211 1.187 dyoung .k_nextparser = &command_root.pb_parser} 212 1.187 dyoung , {.k_word = "metric", .k_nextparser = &parse_metric.pi_parser} 213 1.187 dyoung , {.k_word = "mtu", .k_nextparser = &parse_mtu.pi_parser} 214 1.187 dyoung , {.k_word = "netmask", .k_nextparser = &parse_netmask.pa_parser} 215 1.187 dyoung , {.k_word = "preference", .k_act = "address", 216 1.187 dyoung .k_nextparser = &parse_preference.pi_parser} 217 1.187 dyoung , {.k_word = "prefixlen", .k_nextparser = &parse_prefixlen.pi_parser} 218 1.187 dyoung , {.k_word = "trailers", .k_neg = true, 219 1.187 dyoung .k_exec = notrailers, .k_nextparser = &command_root.pb_parser} 220 1.223 pooka , {.k_word = "linkstr", .k_nextparser = &parse_linkstr.ps_parser } 221 1.223 pooka , {.k_word = "-linkstr", .k_exec = unsetlinkstr, 222 1.223 pooka .k_nextparser = &command_root.pb_parser } 223 1.239 ozaki , {.k_word = "descr", .k_nextparser = &parse_descr.ps_parser} 224 1.239 ozaki , {.k_word = "description", .k_nextparser = &parse_descr.ps_parser} 225 1.239 ozaki , {.k_word = "-descr", .k_exec = unsetifdescr, 226 1.239 ozaki .k_nextparser = &command_root.pb_parser} 227 1.239 ozaki , {.k_word = "-description", .k_exec = unsetifdescr, 228 1.239 ozaki .k_nextparser = &command_root.pb_parser} 229 1.1 cgd }; 230 1.1 cgd 231 1.187 dyoung /* key: clonecmd */ 232 1.198 dyoung static const struct kwinst clonekw[] = { 233 1.205 dyoung {.k_word = "create", .k_type = KW_T_INT, .k_int = SIOCIFCREATE, 234 1.187 dyoung .k_nextparser = &opt_silent_family.pb_parser}, 235 1.205 dyoung {.k_word = "destroy", .k_type = KW_T_INT, .k_int = SIOCIFDESTROY} 236 1.187 dyoung }; 237 1.24 thorpej 238 1.208 dyoung static struct kwinst familykw[24]; 239 1.1 cgd 240 1.187 dyoung struct pterm cloneterm = PTERM_INITIALIZER(&cloneterm, "list cloners", 241 1.187 dyoung list_cloners, "none"); 242 1.187 dyoung 243 1.232 roy struct pterm wait_dad = PTERM_INITIALIZER(&wait_dad, "wait DAD", wait_dad_exec, 244 1.232 roy "none"); 245 1.232 roy 246 1.187 dyoung struct pterm no_cmds = PTERM_INITIALIZER(&no_cmds, "no commands", no_cmds_exec, 247 1.187 dyoung "none"); 248 1.187 dyoung 249 1.187 dyoung struct pkw family_only = 250 1.187 dyoung PKW_INITIALIZER(&family_only, "family-only", NULL, "af", familykw, 251 1.187 dyoung __arraycount(familykw), &no_cmds.pt_parser); 252 1.187 dyoung 253 1.187 dyoung struct paddr address = PADDR_INITIALIZER(&address, 254 1.187 dyoung "local address (address 1)", 255 1.187 dyoung setifaddr, "address", "netmask", NULL, "address", &command_root.pb_parser); 256 1.187 dyoung 257 1.187 dyoung struct paddr dstormask = PADDR_INITIALIZER(&dstormask, 258 1.187 dyoung "destination/netmask (address 2)", 259 1.187 dyoung setifdstormask, "dstormask", NULL, "address", "dstormask", 260 1.187 dyoung &command_root.pb_parser); 261 1.187 dyoung 262 1.187 dyoung struct paddr broadcast = PADDR_INITIALIZER(&broadcast, 263 1.187 dyoung "broadcast address (address 3)", 264 1.187 dyoung setifbroadaddr, "broadcast", NULL, "dstormask", "broadcast", 265 1.187 dyoung &command_root.pb_parser); 266 1.187 dyoung 267 1.223 pooka struct pstr parse_linkstr = PSTR_INITIALIZER(&parse_linkstr, "linkstr", 268 1.223 pooka setlinkstr, "linkstr", &command_root.pb_parser); 269 1.223 pooka 270 1.208 dyoung static SIMPLEQ_HEAD(, afswtch) aflist = SIMPLEQ_HEAD_INITIALIZER(aflist); 271 1.208 dyoung 272 1.209 dyoung static SIMPLEQ_HEAD(, usage_func) usage_funcs = 273 1.209 dyoung SIMPLEQ_HEAD_INITIALIZER(usage_funcs); 274 1.208 dyoung static SIMPLEQ_HEAD(, status_func) status_funcs = 275 1.208 dyoung SIMPLEQ_HEAD_INITIALIZER(status_funcs); 276 1.208 dyoung static SIMPLEQ_HEAD(, statistics_func) statistics_funcs = 277 1.208 dyoung SIMPLEQ_HEAD_INITIALIZER(statistics_funcs); 278 1.208 dyoung static SIMPLEQ_HEAD(, cmdloop_branch) cmdloop_branches = 279 1.208 dyoung SIMPLEQ_HEAD_INITIALIZER(cmdloop_branches); 280 1.208 dyoung 281 1.187 dyoung struct branch opt_clone_brs[] = { 282 1.187 dyoung {.b_nextparser = &cloning.pk_parser} 283 1.187 dyoung , {.b_nextparser = &opt_family.pb_parser} 284 1.187 dyoung }, opt_silent_family_brs[] = { 285 1.187 dyoung {.b_nextparser = &silent_family.pk_parser} 286 1.187 dyoung , {.b_nextparser = &command_root.pb_parser} 287 1.187 dyoung }, opt_family_brs[] = { 288 1.187 dyoung {.b_nextparser = &family.pk_parser} 289 1.187 dyoung , {.b_nextparser = &opt_command.pb_parser} 290 1.187 dyoung }, command_root_brs[] = { 291 1.208 dyoung {.b_nextparser = &ifflags.pk_parser} 292 1.187 dyoung , {.b_nextparser = &ifcaps.pk_parser} 293 1.208 dyoung , {.b_nextparser = &kwmedia.pk_parser} 294 1.187 dyoung , {.b_nextparser = &misc.pk_parser} 295 1.187 dyoung , {.b_nextparser = &address.pa_parser} 296 1.187 dyoung , {.b_nextparser = &dstormask.pa_parser} 297 1.187 dyoung , {.b_nextparser = &broadcast.pa_parser} 298 1.187 dyoung , {.b_nextparser = NULL} 299 1.187 dyoung }, opt_command_brs[] = { 300 1.187 dyoung {.b_nextparser = &no_cmds.pt_parser} 301 1.187 dyoung , {.b_nextparser = &command_root.pb_parser} 302 1.187 dyoung }; 303 1.187 dyoung 304 1.187 dyoung struct branch opt_family_only_brs[] = { 305 1.187 dyoung {.b_nextparser = &no_cmds.pt_parser} 306 1.187 dyoung , {.b_nextparser = &family_only.pk_parser} 307 1.187 dyoung }; 308 1.187 dyoung struct pbranch opt_family_only = PBRANCH_INITIALIZER(&opt_family_only, 309 1.187 dyoung "opt-family-only", opt_family_only_brs, 310 1.187 dyoung __arraycount(opt_family_only_brs), true); 311 1.187 dyoung struct pbranch opt_command = PBRANCH_INITIALIZER(&opt_command, 312 1.187 dyoung "optional command", 313 1.187 dyoung opt_command_brs, __arraycount(opt_command_brs), true); 314 1.187 dyoung 315 1.187 dyoung struct pbranch command_root = PBRANCH_INITIALIZER(&command_root, 316 1.187 dyoung "command-root", command_root_brs, __arraycount(command_root_brs), true); 317 1.187 dyoung 318 1.187 dyoung struct piface iface_opt_family_only = 319 1.187 dyoung PIFACE_INITIALIZER(&iface_opt_family_only, "iface-opt-family-only", 320 1.187 dyoung NULL, "if", &opt_family_only.pb_parser); 321 1.187 dyoung 322 1.187 dyoung struct pkw family = PKW_INITIALIZER(&family, "family", NULL, "af", 323 1.187 dyoung familykw, __arraycount(familykw), &opt_command.pb_parser); 324 1.187 dyoung 325 1.187 dyoung struct pkw silent_family = PKW_INITIALIZER(&silent_family, "silent family", 326 1.187 dyoung NULL, "af", familykw, __arraycount(familykw), &command_root.pb_parser); 327 1.187 dyoung 328 1.208 dyoung struct pkw *family_users[] = {&family_only, &family, &silent_family}; 329 1.208 dyoung 330 1.187 dyoung struct pkw ifcaps = PKW_INITIALIZER(&ifcaps, "ifcaps", setifcaps, 331 1.187 dyoung "ifcap", ifcapskw, __arraycount(ifcapskw), &command_root.pb_parser); 332 1.187 dyoung 333 1.187 dyoung struct pkw ifflags = PKW_INITIALIZER(&ifflags, "ifflags", setifflags, 334 1.187 dyoung "ifflag", ifflagskw, __arraycount(ifflagskw), &command_root.pb_parser); 335 1.187 dyoung 336 1.187 dyoung struct pkw cloning = PKW_INITIALIZER(&cloning, "cloning", clone_command, 337 1.187 dyoung "clonecmd", clonekw, __arraycount(clonekw), NULL); 338 1.187 dyoung 339 1.187 dyoung struct pkw misc = PKW_INITIALIZER(&misc, "misc", NULL, NULL, 340 1.187 dyoung misckw, __arraycount(misckw), NULL); 341 1.187 dyoung 342 1.187 dyoung struct pbranch opt_clone = PBRANCH_INITIALIZER(&opt_clone, 343 1.187 dyoung "opt-clone", opt_clone_brs, __arraycount(opt_clone_brs), true); 344 1.187 dyoung 345 1.187 dyoung struct pbranch opt_silent_family = PBRANCH_INITIALIZER(&opt_silent_family, 346 1.187 dyoung "optional silent family", opt_silent_family_brs, 347 1.187 dyoung __arraycount(opt_silent_family_brs), true); 348 1.187 dyoung 349 1.187 dyoung struct pbranch opt_family = PBRANCH_INITIALIZER(&opt_family, 350 1.187 dyoung "opt-family", opt_family_brs, __arraycount(opt_family_brs), true); 351 1.187 dyoung 352 1.187 dyoung struct piface iface_start = PIFACE_INITIALIZER(&iface_start, 353 1.187 dyoung "iface-opt-family", NULL, "if", &opt_clone.pb_parser); 354 1.187 dyoung 355 1.187 dyoung struct piface iface_only = PIFACE_INITIALIZER(&iface_only, "iface", 356 1.187 dyoung media_status_exec, "if", NULL); 357 1.187 dyoung 358 1.209 dyoung static bool 359 1.209 dyoung flag_is_registered(const char *flags, int flag) 360 1.209 dyoung { 361 1.209 dyoung return flags != NULL && strchr(flags, flag) != NULL; 362 1.209 dyoung } 363 1.209 dyoung 364 1.208 dyoung static int 365 1.209 dyoung check_flag(const char *flags, int flag) 366 1.208 dyoung { 367 1.209 dyoung if (flag_is_registered(flags, flag)) { 368 1.208 dyoung errno = EEXIST; 369 1.208 dyoung return -1; 370 1.208 dyoung } 371 1.208 dyoung 372 1.208 dyoung if (flag >= '0' && flag <= '9') 373 1.208 dyoung return 0; 374 1.208 dyoung if (flag >= 'a' && flag <= 'z') 375 1.208 dyoung return 0; 376 1.208 dyoung if (flag >= 'A' && flag <= 'Z') 377 1.208 dyoung return 0; 378 1.208 dyoung 379 1.208 dyoung errno = EINVAL; 380 1.208 dyoung return -1; 381 1.208 dyoung } 382 1.208 dyoung 383 1.208 dyoung void 384 1.208 dyoung cmdloop_branch_init(cmdloop_branch_t *b, struct parser *p) 385 1.208 dyoung { 386 1.208 dyoung b->b_parser = p; 387 1.208 dyoung } 388 1.208 dyoung 389 1.208 dyoung void 390 1.208 dyoung statistics_func_init(statistics_func_t *f, statistics_cb_t func) 391 1.208 dyoung { 392 1.208 dyoung f->f_func = func; 393 1.208 dyoung } 394 1.208 dyoung 395 1.208 dyoung void 396 1.208 dyoung status_func_init(status_func_t *f, status_cb_t func) 397 1.208 dyoung { 398 1.208 dyoung f->f_func = func; 399 1.208 dyoung } 400 1.208 dyoung 401 1.209 dyoung void 402 1.209 dyoung usage_func_init(usage_func_t *f, usage_cb_t func) 403 1.209 dyoung { 404 1.209 dyoung f->f_func = func; 405 1.209 dyoung } 406 1.209 dyoung 407 1.208 dyoung int 408 1.208 dyoung register_cmdloop_branch(cmdloop_branch_t *b) 409 1.208 dyoung { 410 1.208 dyoung SIMPLEQ_INSERT_TAIL(&cmdloop_branches, b, b_next); 411 1.208 dyoung return 0; 412 1.208 dyoung } 413 1.208 dyoung 414 1.208 dyoung int 415 1.208 dyoung register_statistics(statistics_func_t *f) 416 1.208 dyoung { 417 1.208 dyoung SIMPLEQ_INSERT_TAIL(&statistics_funcs, f, f_next); 418 1.208 dyoung return 0; 419 1.208 dyoung } 420 1.208 dyoung 421 1.208 dyoung int 422 1.208 dyoung register_status(status_func_t *f) 423 1.208 dyoung { 424 1.208 dyoung SIMPLEQ_INSERT_TAIL(&status_funcs, f, f_next); 425 1.208 dyoung return 0; 426 1.208 dyoung } 427 1.208 dyoung 428 1.208 dyoung int 429 1.209 dyoung register_usage(usage_func_t *f) 430 1.209 dyoung { 431 1.209 dyoung SIMPLEQ_INSERT_TAIL(&usage_funcs, f, f_next); 432 1.209 dyoung return 0; 433 1.209 dyoung } 434 1.209 dyoung 435 1.209 dyoung int 436 1.208 dyoung register_family(struct afswtch *af) 437 1.208 dyoung { 438 1.208 dyoung SIMPLEQ_INSERT_TAIL(&aflist, af, af_next); 439 1.208 dyoung return 0; 440 1.208 dyoung } 441 1.227 mbalmer 442 1.208 dyoung int 443 1.208 dyoung register_flag(int flag) 444 1.208 dyoung { 445 1.208 dyoung if (check_flag(gflags, flag) == -1) 446 1.208 dyoung return -1; 447 1.208 dyoung 448 1.208 dyoung if (strlen(gflags) + 1 >= sizeof(gflags)) { 449 1.208 dyoung errno = ENOMEM; 450 1.208 dyoung return -1; 451 1.208 dyoung } 452 1.208 dyoung 453 1.208 dyoung gflags[strlen(gflags)] = flag; 454 1.208 dyoung 455 1.208 dyoung return 0; 456 1.208 dyoung } 457 1.227 mbalmer 458 1.208 dyoung static int 459 1.208 dyoung flag_index(int flag) 460 1.208 dyoung { 461 1.208 dyoung if (flag >= '0' && flag <= '9') 462 1.208 dyoung return flag - '0'; 463 1.208 dyoung if (flag >= 'a' && flag <= 'z') 464 1.208 dyoung return 10 + flag - 'a'; 465 1.208 dyoung if (flag >= 'A' && flag <= 'Z') 466 1.208 dyoung return 10 + 26 + flag - 'a'; 467 1.208 dyoung 468 1.208 dyoung errno = EINVAL; 469 1.208 dyoung return -1; 470 1.208 dyoung } 471 1.208 dyoung 472 1.208 dyoung static bool 473 1.208 dyoung set_flag(int flag) 474 1.208 dyoung { 475 1.208 dyoung int idx; 476 1.208 dyoung 477 1.208 dyoung if ((idx = flag_index(flag)) == -1) 478 1.208 dyoung return false; 479 1.208 dyoung 480 1.208 dyoung return gflagset[idx] = true; 481 1.208 dyoung } 482 1.208 dyoung 483 1.208 dyoung bool 484 1.208 dyoung get_flag(int flag) 485 1.208 dyoung { 486 1.208 dyoung int idx; 487 1.208 dyoung 488 1.208 dyoung if ((idx = flag_index(flag)) == -1) 489 1.208 dyoung return false; 490 1.227 mbalmer 491 1.208 dyoung return gflagset[idx]; 492 1.208 dyoung } 493 1.208 dyoung 494 1.187 dyoung static struct parser * 495 1.187 dyoung init_parser(void) 496 1.187 dyoung { 497 1.208 dyoung cmdloop_branch_t *b; 498 1.208 dyoung 499 1.187 dyoung if (parser_init(&iface_opt_family_only.pif_parser) == -1) 500 1.187 dyoung err(EXIT_FAILURE, "parser_init(iface_opt_family_only)"); 501 1.187 dyoung if (parser_init(&iface_only.pif_parser) == -1) 502 1.187 dyoung err(EXIT_FAILURE, "parser_init(iface_only)"); 503 1.187 dyoung if (parser_init(&iface_start.pif_parser) == -1) 504 1.187 dyoung err(EXIT_FAILURE, "parser_init(iface_start)"); 505 1.227 mbalmer 506 1.208 dyoung SIMPLEQ_FOREACH(b, &cmdloop_branches, b_next) 507 1.208 dyoung pbranch_addbranch(&command_root, b->b_parser); 508 1.187 dyoung 509 1.187 dyoung return &iface_start.pif_parser; 510 1.187 dyoung } 511 1.187 dyoung 512 1.187 dyoung static int 513 1.211 dyoung no_cmds_exec(prop_dictionary_t env, prop_dictionary_t oenv) 514 1.187 dyoung { 515 1.187 dyoung const char *ifname; 516 1.187 dyoung unsigned short ignore; 517 1.187 dyoung 518 1.187 dyoung /* ifname == NULL is ok. It indicates 'ifconfig -a'. */ 519 1.187 dyoung if ((ifname = getifname(env)) == NULL) 520 1.187 dyoung ; 521 1.211 dyoung else if (getifflags(env, oenv, &ignore) == -1) 522 1.187 dyoung err(EXIT_FAILURE, "SIOCGIFFLAGS %s", ifname); 523 1.187 dyoung 524 1.187 dyoung printall(ifname, env); 525 1.187 dyoung exit(EXIT_SUCCESS); 526 1.187 dyoung } 527 1.187 dyoung 528 1.187 dyoung static int 529 1.232 roy wait_dad_exec(prop_dictionary_t env, prop_dictionary_t oenv) 530 1.232 roy { 531 1.232 roy bool waiting; 532 1.232 roy struct ifaddrs *ifaddrs, *ifa; 533 1.232 roy const struct timespec ts = { .tv_sec = 0, .tv_nsec = WAIT_DAD }; 534 1.236 roy struct timespec now, end_det, end; 535 1.234 roy const struct afswtch *afp; 536 1.232 roy 537 1.232 roy if (wflag_secs) { 538 1.236 roy const struct timespec tent = 539 1.236 roy { .tv_sec = wflag_secs, .tv_nsec = 0}; 540 1.236 roy const struct timespec det = 541 1.236 roy { .tv_sec = Wflag_secs, .tv_nsec = 0}; 542 1.236 roy 543 1.232 roy if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) 544 1.232 roy err(EXIT_FAILURE, "clock_gettime"); 545 1.236 roy timespecadd(&now, &tent, &end); 546 1.236 roy if (Wflag_secs) 547 1.236 roy timespecadd(&now, &det, &end_det); 548 1.236 roy else 549 1.236 roy timespecclear(&end_det); 550 1.236 roy } else { 551 1.236 roy timespecclear(&end_det); 552 1.236 roy timespecclear(&end); 553 1.232 roy } 554 1.232 roy 555 1.232 roy if (getifaddrs(&ifaddrs) == -1) 556 1.232 roy err(EXIT_FAILURE, "getifaddrs"); 557 1.232 roy 558 1.232 roy for (;;) { 559 1.232 roy waiting = false; 560 1.232 roy for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 561 1.232 roy if (ifa->ifa_addr == NULL) 562 1.232 roy continue; 563 1.234 roy afp = lookup_af_bynum(ifa->ifa_addr->sa_family); 564 1.236 roy if (afp && 565 1.236 roy ((afp->af_addr_tentative_or_detached && 566 1.236 roy ifa->ifa_flags & IFF_UP && 567 1.236 roy timespecisset(&end_det) && 568 1.236 roy timespeccmp(&now, &end_det, <) && 569 1.236 roy afp->af_addr_tentative_or_detached(ifa)) || 570 1.236 roy (afp->af_addr_tentative && 571 1.236 roy afp->af_addr_tentative(ifa)))) 572 1.234 roy { 573 1.234 roy waiting = true; 574 1.234 roy break; 575 1.232 roy } 576 1.232 roy } 577 1.232 roy if (!waiting) 578 1.232 roy break; 579 1.232 roy nanosleep(&ts, NULL); 580 1.232 roy if (wflag_secs) { 581 1.232 roy if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) 582 1.232 roy err(EXIT_FAILURE, "clock_gettime"); 583 1.232 roy if (timespeccmp(&now, &end, >)) 584 1.232 roy errx(EXIT_FAILURE, "timed out"); 585 1.232 roy } 586 1.232 roy } 587 1.232 roy 588 1.232 roy freeifaddrs(ifaddrs); 589 1.232 roy exit(EXIT_SUCCESS); 590 1.232 roy } 591 1.232 roy 592 1.232 roy static int 593 1.211 dyoung media_status_exec(prop_dictionary_t env, prop_dictionary_t oenv) 594 1.187 dyoung { 595 1.187 dyoung const char *ifname; 596 1.187 dyoung unsigned short ignore; 597 1.187 dyoung 598 1.187 dyoung /* ifname == NULL is ok. It indicates 'ifconfig -a'. */ 599 1.187 dyoung if ((ifname = getifname(env)) == NULL) 600 1.187 dyoung ; 601 1.211 dyoung else if (getifflags(env, oenv, &ignore) == -1) 602 1.187 dyoung err(EXIT_FAILURE, "SIOCGIFFLAGS %s", ifname); 603 1.187 dyoung 604 1.187 dyoung exit(carrier(env)); 605 1.187 dyoung } 606 1.1 cgd 607 1.192 dyoung static void 608 1.201 dyoung do_setifcaps(prop_dictionary_t env) 609 1.192 dyoung { 610 1.192 dyoung struct ifcapreq ifcr; 611 1.192 dyoung prop_data_t d; 612 1.192 dyoung 613 1.193 dyoung d = (prop_data_t )prop_dictionary_get(env, "ifcaps"); 614 1.193 dyoung if (d == NULL) 615 1.192 dyoung return; 616 1.192 dyoung 617 1.193 dyoung assert(sizeof(ifcr) == prop_data_size(d)); 618 1.193 dyoung 619 1.242 thorpej memcpy(&ifcr, prop_data_value(d), sizeof(ifcr)); 620 1.201 dyoung if (direct_ioctl(env, SIOCSIFCAP, &ifcr) == -1) 621 1.192 dyoung err(EXIT_FAILURE, "SIOCSIFCAP"); 622 1.192 dyoung } 623 1.192 dyoung 624 1.16 cgd int 625 1.187 dyoung main(int argc, char **argv) 626 1.1 cgd { 627 1.187 dyoung const struct afswtch *afp; 628 1.236 roy int af, s, e; 629 1.208 dyoung bool aflag = false, Cflag = false; 630 1.187 dyoung struct match match[32]; 631 1.187 dyoung size_t nmatch; 632 1.187 dyoung struct parser *start; 633 1.187 dyoung int ch, narg = 0, rc; 634 1.211 dyoung prop_dictionary_t env, oenv; 635 1.187 dyoung const char *ifname; 636 1.187 dyoung 637 1.187 dyoung memset(match, 0, sizeof(match)); 638 1.187 dyoung 639 1.208 dyoung init_afs(); 640 1.208 dyoung 641 1.187 dyoung start = init_parser(); 642 1.24 thorpej 643 1.24 thorpej /* Parse command-line options */ 644 1.227 mbalmer Nflag = vflag = zflag = false; 645 1.227 mbalmer aflag = argc == 1 ? true : false; 646 1.227 mbalmer if (aflag) 647 1.227 mbalmer start = &opt_family_only.pb_parser; 648 1.227 mbalmer 649 1.208 dyoung while ((ch = getopt(argc, argv, gflags)) != -1) { 650 1.24 thorpej switch (ch) { 651 1.49 christos case 'A': 652 1.107 itojun warnx("-A is deprecated"); 653 1.49 christos break; 654 1.49 christos 655 1.24 thorpej case 'a': 656 1.208 dyoung aflag = true; 657 1.24 thorpej break; 658 1.24 thorpej 659 1.54 sommerfe case 'b': 660 1.208 dyoung bflag = true; 661 1.54 sommerfe break; 662 1.227 mbalmer 663 1.87 thorpej case 'C': 664 1.208 dyoung Cflag = true; 665 1.87 thorpej break; 666 1.87 thorpej 667 1.34 lukem case 'd': 668 1.208 dyoung dflag = true; 669 1.34 lukem break; 670 1.169 rpaulo case 'h': 671 1.208 dyoung hflag = true; 672 1.169 rpaulo break; 673 1.31 thorpej case 'l': 674 1.208 dyoung lflag = true; 675 1.24 thorpej break; 676 1.220 dyoung case 'N': 677 1.220 dyoung Nflag = true; 678 1.220 dyoung break; 679 1.1 cgd 680 1.54 sommerfe case 's': 681 1.208 dyoung sflag = true; 682 1.54 sommerfe break; 683 1.54 sommerfe 684 1.34 lukem case 'u': 685 1.208 dyoung uflag = true; 686 1.34 lukem break; 687 1.34 lukem 688 1.124 matt case 'v': 689 1.208 dyoung vflag = true; 690 1.124 matt break; 691 1.124 matt 692 1.232 roy case 'w': 693 1.232 roy wflag = true; 694 1.236 roy wflag_secs = strtoi(optarg, NULL, 10, 0, INT32_MAX, &e); 695 1.236 roy if (e) 696 1.236 roy errx(EXIT_FAILURE, "%s: not a number", optarg); 697 1.236 roy break; 698 1.236 roy 699 1.236 roy case 'W': 700 1.236 roy Wflag = true; 701 1.236 roy Wflag_secs = strtoi(optarg, NULL, 10, 0, INT32_MAX, &e); 702 1.236 roy if (e) 703 1.232 roy errx(EXIT_FAILURE, "%s: not a number", optarg); 704 1.232 roy break; 705 1.232 roy 706 1.134 perry case 'z': 707 1.208 dyoung zflag = true; 708 1.134 perry break; 709 1.134 perry 710 1.24 thorpej default: 711 1.208 dyoung if (!set_flag(ch)) 712 1.208 dyoung usage(); 713 1.208 dyoung break; 714 1.24 thorpej } 715 1.187 dyoung switch (ch) { 716 1.187 dyoung case 'a': 717 1.187 dyoung start = &opt_family_only.pb_parser; 718 1.187 dyoung break; 719 1.187 dyoung 720 1.187 dyoung case 'L': 721 1.187 dyoung case 'm': 722 1.187 dyoung case 'z': 723 1.187 dyoung if (start != &opt_family_only.pb_parser) 724 1.187 dyoung start = &iface_opt_family_only.pif_parser; 725 1.187 dyoung break; 726 1.187 dyoung case 'C': 727 1.187 dyoung start = &cloneterm.pt_parser; 728 1.187 dyoung break; 729 1.187 dyoung case 'l': 730 1.187 dyoung start = &no_cmds.pt_parser; 731 1.187 dyoung break; 732 1.187 dyoung case 's': 733 1.187 dyoung if (start != &no_cmds.pt_parser && 734 1.187 dyoung start != &opt_family_only.pb_parser) 735 1.187 dyoung start = &iface_only.pif_parser; 736 1.187 dyoung break; 737 1.232 roy case 'w': 738 1.232 roy start = &wait_dad.pt_parser; 739 1.232 roy break; 740 1.187 dyoung default: 741 1.187 dyoung break; 742 1.187 dyoung } 743 1.1 cgd } 744 1.24 thorpej argc -= optind; 745 1.24 thorpej argv += optind; 746 1.24 thorpej 747 1.31 thorpej /* 748 1.232 roy * -l means "list all interfaces", and is mutually exclusive with 749 1.31 thorpej * all other flags/commands. 750 1.31 thorpej * 751 1.87 thorpej * -C means "list all names of cloners", and it mutually exclusive 752 1.87 thorpej * with all other flags/commands. 753 1.87 thorpej * 754 1.31 thorpej * -a means "print status of all interfaces". 755 1.232 roy * 756 1.250 andvar * -w means "spin until DAD completes for all addresses", and is 757 1.250 andvar * mutually exclusive with all other flags/commands. 758 1.31 thorpej */ 759 1.232 roy if ((lflag || Cflag || wflag) && 760 1.232 roy (aflag || get_flag('m') || vflag || zflag)) 761 1.54 sommerfe usage(); 762 1.232 roy if ((lflag || Cflag || wflag) && get_flag('L')) 763 1.31 thorpej usage(); 764 1.232 roy if ((lflag && Cflag) || (lflag & wflag) || (Cflag && wflag)) 765 1.87 thorpej usage(); 766 1.24 thorpej 767 1.187 dyoung nmatch = __arraycount(match); 768 1.187 dyoung 769 1.187 dyoung rc = parse(argc, argv, start, match, &nmatch, &narg); 770 1.187 dyoung if (rc != 0) 771 1.24 thorpej usage(); 772 1.24 thorpej 773 1.224 pooka if (prog_init && prog_init() == -1) 774 1.224 pooka err(1, "rump client init"); 775 1.224 pooka 776 1.211 dyoung if ((oenv = prop_dictionary_create()) == NULL) 777 1.187 dyoung err(EXIT_FAILURE, "%s: prop_dictionary_create", __func__); 778 1.187 dyoung 779 1.211 dyoung if (matches_exec(match, oenv, nmatch) == -1) 780 1.187 dyoung err(EXIT_FAILURE, "exec_matches"); 781 1.81 thorpej 782 1.187 dyoung argc -= narg; 783 1.187 dyoung argv += narg; 784 1.24 thorpej 785 1.187 dyoung env = (nmatch > 0) ? match[(int)nmatch - 1].m_env : NULL; 786 1.187 dyoung if (env == NULL) 787 1.211 dyoung env = oenv; 788 1.229 apb else { 789 1.211 dyoung env = prop_dictionary_augment(env, oenv); 790 1.229 apb if (env == NULL) 791 1.229 apb err(EXIT_FAILURE, "%s: prop_dictionary_augment", 792 1.229 apb __func__); 793 1.229 apb } 794 1.24 thorpej 795 1.187 dyoung /* Process any media commands that may have been issued. */ 796 1.187 dyoung process_media_commands(env); 797 1.24 thorpej 798 1.208 dyoung if ((af = getaf(env)) == -1) 799 1.187 dyoung af = AF_INET; 800 1.54 sommerfe 801 1.187 dyoung if ((s = getsock(af)) == -1) 802 1.187 dyoung err(EXIT_FAILURE, "%s: getsock", __func__); 803 1.51 thorpej 804 1.187 dyoung if ((ifname = getifname(env)) == NULL) 805 1.187 dyoung err(EXIT_FAILURE, "%s: getifname", __func__); 806 1.24 thorpej 807 1.187 dyoung if ((afp = lookup_af_bynum(af)) == NULL) 808 1.187 dyoung errx(EXIT_FAILURE, "%s: lookup_af_bynum", __func__); 809 1.1 cgd 810 1.208 dyoung assert(afp->af_addr_commit != NULL); 811 1.211 dyoung (*afp->af_addr_commit)(env, oenv); 812 1.21 gwr 813 1.187 dyoung do_setifpreference(env); 814 1.201 dyoung do_setifcaps(env); 815 1.238 msaitoh do_setethercaps(env); 816 1.108 thorpej 817 1.208 dyoung exit(EXIT_SUCCESS); 818 1.208 dyoung } 819 1.24 thorpej 820 1.208 dyoung static void 821 1.208 dyoung init_afs(void) 822 1.208 dyoung { 823 1.214 lukem size_t i; 824 1.208 dyoung const struct afswtch *afp; 825 1.208 dyoung struct kwinst kw = {.k_type = KW_T_INT}; 826 1.208 dyoung 827 1.208 dyoung SIMPLEQ_FOREACH(afp, &aflist, af_next) { 828 1.208 dyoung kw.k_word = afp->af_name; 829 1.208 dyoung kw.k_int = afp->af_af; 830 1.208 dyoung for (i = 0; i < __arraycount(familykw); i++) { 831 1.208 dyoung if (familykw[i].k_word == NULL) { 832 1.208 dyoung familykw[i] = kw; 833 1.208 dyoung break; 834 1.208 dyoung } 835 1.208 dyoung } 836 1.208 dyoung } 837 1.24 thorpej } 838 1.24 thorpej 839 1.160 thorpej const struct afswtch * 840 1.158 thorpej lookup_af_bynum(int afnum) 841 1.158 thorpej { 842 1.208 dyoung const struct afswtch *afp; 843 1.158 thorpej 844 1.208 dyoung SIMPLEQ_FOREACH(afp, &aflist, af_next) { 845 1.208 dyoung if (afp->af_af == afnum) 846 1.208 dyoung break; 847 1.208 dyoung } 848 1.208 dyoung return afp; 849 1.158 thorpej } 850 1.158 thorpej 851 1.13 mycroft void 852 1.187 dyoung printall(const char *ifname, prop_dictionary_t env0) 853 1.5 deraadt { 854 1.78 itojun struct ifaddrs *ifap, *ifa; 855 1.189 dyoung prop_dictionary_t env, oenv; 856 1.78 itojun int idx; 857 1.78 itojun char *p; 858 1.78 itojun 859 1.187 dyoung if (env0 == NULL) 860 1.187 dyoung env = prop_dictionary_create(); 861 1.187 dyoung else 862 1.187 dyoung env = prop_dictionary_copy_mutable(env0); 863 1.187 dyoung 864 1.189 dyoung oenv = prop_dictionary_create(); 865 1.189 dyoung 866 1.189 dyoung if (env == NULL || oenv == NULL) 867 1.187 dyoung errx(EXIT_FAILURE, "%s: prop_dictionary_copy/create", __func__); 868 1.187 dyoung 869 1.78 itojun if (getifaddrs(&ifap) != 0) 870 1.120 atatat err(EXIT_FAILURE, "getifaddrs"); 871 1.78 itojun p = NULL; 872 1.78 itojun idx = 0; 873 1.78 itojun for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 874 1.187 dyoung if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0) 875 1.107 itojun continue; 876 1.78 itojun if (p && strcmp(p, ifa->ifa_name) == 0) 877 1.78 itojun continue; 878 1.242 thorpej if (!prop_dictionary_set_string(env, "if", ifa->ifa_name)) 879 1.140 itojun continue; 880 1.78 itojun p = ifa->ifa_name; 881 1.78 itojun 882 1.135 lukem if (bflag && (ifa->ifa_flags & IFF_BROADCAST) == 0) 883 1.78 itojun continue; 884 1.78 itojun if (dflag && (ifa->ifa_flags & IFF_UP) != 0) 885 1.78 itojun continue; 886 1.78 itojun if (uflag && (ifa->ifa_flags & IFF_UP) == 0) 887 1.78 itojun continue; 888 1.78 itojun 889 1.251 ozaki if (sflag && link_state(env) == LINK_STATE_DOWN) 890 1.78 itojun continue; 891 1.78 itojun idx++; 892 1.78 itojun /* 893 1.78 itojun * Are we just listing the interfaces? 894 1.78 itojun */ 895 1.78 itojun if (lflag) { 896 1.78 itojun if (idx > 1) 897 1.147 dsl printf(" "); 898 1.187 dyoung fputs(ifa->ifa_name, stdout); 899 1.78 itojun continue; 900 1.78 itojun } 901 1.78 itojun 902 1.248 roy status(env, oenv); 903 1.78 itojun } 904 1.78 itojun if (lflag) 905 1.147 dsl printf("\n"); 906 1.187 dyoung prop_object_release((prop_object_t)env); 907 1.189 dyoung prop_object_release((prop_object_t)oenv); 908 1.78 itojun freeifaddrs(ifap); 909 1.87 thorpej } 910 1.87 thorpej 911 1.208 dyoung static int 912 1.187 dyoung list_cloners(prop_dictionary_t env, prop_dictionary_t oenv) 913 1.87 thorpej { 914 1.87 thorpej struct if_clonereq ifcr; 915 1.87 thorpej char *cp, *buf; 916 1.187 dyoung int idx, s; 917 1.87 thorpej 918 1.87 thorpej memset(&ifcr, 0, sizeof(ifcr)); 919 1.87 thorpej 920 1.187 dyoung s = getsock(AF_INET); 921 1.87 thorpej 922 1.224 pooka if (prog_ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 923 1.120 atatat err(EXIT_FAILURE, "SIOCIFGCLONERS for count"); 924 1.87 thorpej 925 1.87 thorpej buf = malloc(ifcr.ifcr_total * IFNAMSIZ); 926 1.87 thorpej if (buf == NULL) 927 1.120 atatat err(EXIT_FAILURE, "unable to allocate cloner name buffer"); 928 1.87 thorpej 929 1.87 thorpej ifcr.ifcr_count = ifcr.ifcr_total; 930 1.87 thorpej ifcr.ifcr_buffer = buf; 931 1.87 thorpej 932 1.224 pooka if (prog_ioctl(s, SIOCIFGCLONERS, &ifcr) == -1) 933 1.120 atatat err(EXIT_FAILURE, "SIOCIFGCLONERS for names"); 934 1.87 thorpej 935 1.87 thorpej /* 936 1.87 thorpej * In case some disappeared in the mean time, clamp it down. 937 1.87 thorpej */ 938 1.87 thorpej if (ifcr.ifcr_count > ifcr.ifcr_total) 939 1.87 thorpej ifcr.ifcr_count = ifcr.ifcr_total; 940 1.87 thorpej 941 1.87 thorpej for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) { 942 1.87 thorpej if (idx > 0) 943 1.147 dsl printf(" "); 944 1.87 thorpej printf("%s", cp); 945 1.87 thorpej } 946 1.87 thorpej 947 1.147 dsl printf("\n"); 948 1.87 thorpej free(buf); 949 1.187 dyoung exit(EXIT_SUCCESS); 950 1.5 deraadt } 951 1.5 deraadt 952 1.187 dyoung static int 953 1.211 dyoung clone_command(prop_dictionary_t env, prop_dictionary_t oenv) 954 1.81 thorpej { 955 1.188 dyoung int64_t cmd; 956 1.187 dyoung 957 1.188 dyoung if (!prop_dictionary_get_int64(env, "clonecmd", &cmd)) { 958 1.187 dyoung errno = ENOENT; 959 1.187 dyoung return -1; 960 1.187 dyoung } 961 1.187 dyoung 962 1.201 dyoung if (indirect_ioctl(env, (unsigned long)cmd, NULL) == -1) { 963 1.187 dyoung warn("%s", __func__); 964 1.187 dyoung return -1; 965 1.187 dyoung } 966 1.187 dyoung return 0; 967 1.81 thorpej } 968 1.81 thorpej 969 1.81 thorpej /*ARGSUSED*/ 970 1.208 dyoung static int 971 1.211 dyoung setifaddr(prop_dictionary_t env, prop_dictionary_t oenv) 972 1.81 thorpej { 973 1.187 dyoung const struct paddr_prefix *pfx0; 974 1.187 dyoung struct paddr_prefix *pfx; 975 1.187 dyoung prop_data_t d; 976 1.208 dyoung int af; 977 1.187 dyoung 978 1.187 dyoung if ((af = getaf(env)) == -1) 979 1.187 dyoung af = AF_INET; 980 1.187 dyoung 981 1.187 dyoung d = (prop_data_t)prop_dictionary_get(env, "address"); 982 1.187 dyoung assert(d != NULL); 983 1.242 thorpej pfx0 = prop_data_value(d); 984 1.81 thorpej 985 1.194 dyoung if (pfx0->pfx_len >= 0) { 986 1.187 dyoung pfx = prefixlen_to_mask(af, pfx0->pfx_len); 987 1.187 dyoung if (pfx == NULL) 988 1.187 dyoung err(EXIT_FAILURE, "prefixlen_to_mask"); 989 1.187 dyoung free(pfx); 990 1.187 dyoung } 991 1.187 dyoung 992 1.187 dyoung return 0; 993 1.1 cgd } 994 1.1 cgd 995 1.208 dyoung static int 996 1.211 dyoung setifnetmask(prop_dictionary_t env, prop_dictionary_t oenv) 997 1.1 cgd { 998 1.187 dyoung prop_data_t d; 999 1.187 dyoung 1000 1.187 dyoung d = (prop_data_t)prop_dictionary_get(env, "dstormask"); 1001 1.187 dyoung assert(d != NULL); 1002 1.187 dyoung 1003 1.211 dyoung if (!prop_dictionary_set(oenv, "netmask", (prop_object_t)d)) 1004 1.187 dyoung return -1; 1005 1.187 dyoung 1006 1.187 dyoung return 0; 1007 1.1 cgd } 1008 1.1 cgd 1009 1.208 dyoung static int 1010 1.211 dyoung setifbroadaddr(prop_dictionary_t env, prop_dictionary_t oenv) 1011 1.1 cgd { 1012 1.187 dyoung prop_data_t d; 1013 1.187 dyoung unsigned short flags; 1014 1.187 dyoung 1015 1.211 dyoung if (getifflags(env, oenv, &flags) == -1) 1016 1.187 dyoung err(EXIT_FAILURE, "%s: getifflags", __func__); 1017 1.187 dyoung 1018 1.187 dyoung if ((flags & IFF_BROADCAST) == 0) 1019 1.187 dyoung errx(EXIT_FAILURE, "not a broadcast interface"); 1020 1.187 dyoung 1021 1.187 dyoung d = (prop_data_t)prop_dictionary_get(env, "broadcast"); 1022 1.187 dyoung assert(d != NULL); 1023 1.187 dyoung 1024 1.211 dyoung if (!prop_dictionary_set(oenv, "broadcast", (prop_object_t)d)) 1025 1.187 dyoung return -1; 1026 1.187 dyoung 1027 1.187 dyoung return 0; 1028 1.1 cgd } 1029 1.1 cgd 1030 1.1 cgd /*ARGSUSED*/ 1031 1.208 dyoung static int 1032 1.211 dyoung notrailers(prop_dictionary_t env, prop_dictionary_t oenv) 1033 1.13 mycroft { 1034 1.34 lukem puts("Note: trailers are no longer sent, but always received"); 1035 1.187 dyoung return 0; 1036 1.13 mycroft } 1037 1.13 mycroft 1038 1.13 mycroft /*ARGSUSED*/ 1039 1.208 dyoung static int 1040 1.211 dyoung setifdstormask(prop_dictionary_t env, prop_dictionary_t oenv) 1041 1.1 cgd { 1042 1.187 dyoung const char *key; 1043 1.187 dyoung prop_data_t d; 1044 1.187 dyoung unsigned short flags; 1045 1.187 dyoung 1046 1.211 dyoung if (getifflags(env, oenv, &flags) == -1) 1047 1.187 dyoung err(EXIT_FAILURE, "%s: getifflags", __func__); 1048 1.187 dyoung 1049 1.187 dyoung d = (prop_data_t)prop_dictionary_get(env, "dstormask"); 1050 1.187 dyoung assert(d != NULL); 1051 1.187 dyoung 1052 1.187 dyoung if ((flags & IFF_BROADCAST) == 0) { 1053 1.187 dyoung key = "dst"; 1054 1.187 dyoung } else { 1055 1.187 dyoung key = "netmask"; 1056 1.187 dyoung } 1057 1.187 dyoung 1058 1.211 dyoung if (!prop_dictionary_set(oenv, key, (prop_object_t)d)) 1059 1.187 dyoung return -1; 1060 1.187 dyoung 1061 1.187 dyoung return 0; 1062 1.1 cgd } 1063 1.1 cgd 1064 1.208 dyoung static int 1065 1.211 dyoung setifflags(prop_dictionary_t env, prop_dictionary_t oenv) 1066 1.1 cgd { 1067 1.201 dyoung struct ifreq ifr; 1068 1.189 dyoung int64_t ifflag; 1069 1.189 dyoung bool rc; 1070 1.187 dyoung 1071 1.189 dyoung rc = prop_dictionary_get_int64(env, "ifflag", &ifflag); 1072 1.189 dyoung assert(rc); 1073 1.79 enami 1074 1.240 msaitoh if (direct_ioctl(env, SIOCGIFFLAGS, &ifr) == -1) 1075 1.187 dyoung return -1; 1076 1.187 dyoung 1077 1.187 dyoung if (ifflag < 0) { 1078 1.187 dyoung ifflag = -ifflag; 1079 1.201 dyoung ifr.ifr_flags &= ~ifflag; 1080 1.1 cgd } else 1081 1.201 dyoung ifr.ifr_flags |= ifflag; 1082 1.187 dyoung 1083 1.201 dyoung if (direct_ioctl(env, SIOCSIFFLAGS, &ifr) == -1) 1084 1.187 dyoung return -1; 1085 1.187 dyoung 1086 1.227 mbalmer return 0; 1087 1.187 dyoung } 1088 1.187 dyoung 1089 1.187 dyoung static int 1090 1.187 dyoung getifcaps(prop_dictionary_t env, prop_dictionary_t oenv, struct ifcapreq *oifcr) 1091 1.187 dyoung { 1092 1.187 dyoung bool rc; 1093 1.187 dyoung struct ifcapreq ifcr; 1094 1.187 dyoung const struct ifcapreq *tmpifcr; 1095 1.187 dyoung prop_data_t capdata; 1096 1.187 dyoung 1097 1.187 dyoung capdata = (prop_data_t)prop_dictionary_get(env, "ifcaps"); 1098 1.187 dyoung 1099 1.187 dyoung if (capdata != NULL) { 1100 1.242 thorpej tmpifcr = prop_data_value(capdata); 1101 1.187 dyoung *oifcr = *tmpifcr; 1102 1.187 dyoung return 0; 1103 1.187 dyoung } 1104 1.187 dyoung 1105 1.201 dyoung (void)direct_ioctl(env, SIOCGIFCAP, &ifcr); 1106 1.187 dyoung *oifcr = ifcr; 1107 1.187 dyoung 1108 1.242 thorpej capdata = prop_data_create_copy(&ifcr, sizeof(ifcr)); 1109 1.187 dyoung 1110 1.187 dyoung rc = prop_dictionary_set(oenv, "ifcaps", capdata); 1111 1.187 dyoung 1112 1.187 dyoung prop_object_release((prop_object_t)capdata); 1113 1.187 dyoung 1114 1.190 dyoung return rc ? 0 : -1; 1115 1.1 cgd } 1116 1.1 cgd 1117 1.187 dyoung static int 1118 1.187 dyoung setifcaps(prop_dictionary_t env, prop_dictionary_t oenv) 1119 1.108 thorpej { 1120 1.189 dyoung int64_t ifcap; 1121 1.189 dyoung bool rc; 1122 1.187 dyoung prop_data_t capdata; 1123 1.187 dyoung struct ifcapreq ifcr; 1124 1.187 dyoung 1125 1.189 dyoung rc = prop_dictionary_get_int64(env, "ifcap", &ifcap); 1126 1.189 dyoung assert(rc); 1127 1.189 dyoung 1128 1.187 dyoung if (getifcaps(env, oenv, &ifcr) == -1) 1129 1.187 dyoung return -1; 1130 1.187 dyoung 1131 1.187 dyoung if (ifcap < 0) { 1132 1.187 dyoung ifcap = -ifcap; 1133 1.187 dyoung ifcr.ifcr_capenable &= ~ifcap; 1134 1.108 thorpej } else 1135 1.187 dyoung ifcr.ifcr_capenable |= ifcap; 1136 1.187 dyoung 1137 1.242 thorpej if ((capdata = prop_data_create_copy(&ifcr, sizeof(ifcr))) == NULL) 1138 1.187 dyoung return -1; 1139 1.108 thorpej 1140 1.191 dyoung rc = prop_dictionary_set(oenv, "ifcaps", capdata); 1141 1.190 dyoung prop_object_release((prop_object_t)capdata); 1142 1.187 dyoung 1143 1.190 dyoung return rc ? 0 : -1; 1144 1.108 thorpej } 1145 1.108 thorpej 1146 1.187 dyoung static int 1147 1.211 dyoung setifmetric(prop_dictionary_t env, prop_dictionary_t oenv) 1148 1.1 cgd { 1149 1.187 dyoung struct ifreq ifr; 1150 1.189 dyoung bool rc; 1151 1.189 dyoung int64_t metric; 1152 1.187 dyoung 1153 1.189 dyoung rc = prop_dictionary_get_int64(env, "metric", &metric); 1154 1.189 dyoung assert(rc); 1155 1.125 itojun 1156 1.189 dyoung ifr.ifr_metric = metric; 1157 1.201 dyoung if (direct_ioctl(env, SIOCSIFMETRIC, &ifr) == -1) 1158 1.13 mycroft warn("SIOCSIFMETRIC"); 1159 1.187 dyoung return 0; 1160 1.1 cgd } 1161 1.1 cgd 1162 1.187 dyoung static void 1163 1.187 dyoung do_setifpreference(prop_dictionary_t env) 1164 1.178 dyoung { 1165 1.178 dyoung struct if_addrprefreq ifap; 1166 1.187 dyoung prop_data_t d; 1167 1.187 dyoung const struct paddr_prefix *pfx; 1168 1.187 dyoung 1169 1.189 dyoung memset(&ifap, 0, sizeof(ifap)); 1170 1.189 dyoung 1171 1.189 dyoung if (!prop_dictionary_get_int16(env, "preference", 1172 1.189 dyoung &ifap.ifap_preference)) 1173 1.227 mbalmer return; 1174 1.187 dyoung 1175 1.187 dyoung d = (prop_data_t)prop_dictionary_get(env, "address"); 1176 1.187 dyoung assert(d != NULL); 1177 1.189 dyoung 1178 1.242 thorpej pfx = prop_data_value(d); 1179 1.187 dyoung 1180 1.187 dyoung memcpy(&ifap.ifap_addr, &pfx->pfx_addr, 1181 1.187 dyoung MIN(sizeof(ifap.ifap_addr), pfx->pfx_addr.sa_len)); 1182 1.201 dyoung if (direct_ioctl(env, SIOCSIFADDRPREF, &ifap) == -1) 1183 1.178 dyoung warn("SIOCSIFADDRPREF"); 1184 1.178 dyoung } 1185 1.178 dyoung 1186 1.187 dyoung static int 1187 1.211 dyoung setifmtu(prop_dictionary_t env, prop_dictionary_t oenv) 1188 1.33 is { 1189 1.189 dyoung int64_t mtu; 1190 1.189 dyoung bool rc; 1191 1.187 dyoung struct ifreq ifr; 1192 1.125 itojun 1193 1.189 dyoung rc = prop_dictionary_get_int64(env, "mtu", &mtu); 1194 1.189 dyoung assert(rc); 1195 1.187 dyoung 1196 1.189 dyoung ifr.ifr_mtu = mtu; 1197 1.201 dyoung if (direct_ioctl(env, SIOCSIFMTU, &ifr) == -1) 1198 1.33 is warn("SIOCSIFMTU"); 1199 1.33 is 1200 1.187 dyoung return 0; 1201 1.88 onoe } 1202 1.88 onoe 1203 1.208 dyoung static int 1204 1.251 ozaki link_state(prop_dictionary_t env) 1205 1.54 sommerfe { 1206 1.247 roy struct ifdatareq ifdr = { .ifdr_data.ifi_link_state = 0 }; 1207 1.54 sommerfe 1208 1.247 roy if (direct_ioctl(env, SIOCGIFDATA, &ifdr) == -1) 1209 1.251 ozaki return -1; 1210 1.251 ozaki 1211 1.251 ozaki return ifdr.ifdr_data.ifi_link_state; 1212 1.251 ozaki } 1213 1.251 ozaki 1214 1.251 ozaki static const char * 1215 1.251 ozaki link_state_str(int state) 1216 1.251 ozaki { 1217 1.251 ozaki 1218 1.251 ozaki switch (state) { 1219 1.251 ozaki case LINK_STATE_UNKNOWN: 1220 1.251 ozaki return "unknown"; 1221 1.251 ozaki case LINK_STATE_DOWN: 1222 1.251 ozaki return "down"; 1223 1.251 ozaki case LINK_STATE_UP: 1224 1.251 ozaki return "up"; 1225 1.251 ozaki default: /* Assume -1 */ 1226 1.251 ozaki return "error"; 1227 1.251 ozaki } 1228 1.251 ozaki } 1229 1.244 roy 1230 1.251 ozaki static int 1231 1.251 ozaki carrier(prop_dictionary_t env) 1232 1.251 ozaki { 1233 1.251 ozaki switch (link_state(env)) { 1234 1.251 ozaki case -1: 1235 1.251 ozaki case LINK_STATE_DOWN: 1236 1.247 roy return EXIT_FAILURE; 1237 1.251 ozaki default: 1238 1.251 ozaki /* Assume UP if UNKNOWN */ 1239 1.187 dyoung return EXIT_SUCCESS; 1240 1.251 ozaki } 1241 1.54 sommerfe } 1242 1.54 sommerfe 1243 1.208 dyoung static void 1244 1.208 dyoung print_plural(const char *prefix, uint64_t n, const char *unit) 1245 1.208 dyoung { 1246 1.208 dyoung printf("%s%" PRIu64 " %s%s", prefix, n, unit, (n == 1) ? "" : "s"); 1247 1.208 dyoung } 1248 1.63 thorpej 1249 1.208 dyoung static void 1250 1.208 dyoung print_human_bytes(bool humanize, uint64_t n) 1251 1.208 dyoung { 1252 1.208 dyoung char buf[5]; 1253 1.208 dyoung 1254 1.208 dyoung if (humanize) { 1255 1.208 dyoung (void)humanize_number(buf, sizeof(buf), 1256 1.208 dyoung (int64_t)n, "", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL); 1257 1.208 dyoung printf(", %s byte%s", buf, (atof(buf) == 1.0) ? "" : "s"); 1258 1.208 dyoung } else 1259 1.208 dyoung print_plural(", ", n, "byte"); 1260 1.208 dyoung } 1261 1.63 thorpej 1262 1.1 cgd /* 1263 1.1 cgd * Print the status of the interface. If an address family was 1264 1.1 cgd * specified, show it and it only; otherwise, show them all. 1265 1.1 cgd */ 1266 1.228 pgoyette 1267 1.228 pgoyette #define MAX_PRINT_LEN 58 /* XXX need a better way to determine this! */ 1268 1.228 pgoyette 1269 1.16 cgd void 1270 1.248 roy status(prop_dictionary_t env, prop_dictionary_t oenv) 1271 1.1 cgd { 1272 1.208 dyoung status_func_t *status_f; 1273 1.208 dyoung statistics_func_t *statistics_f; 1274 1.124 matt struct ifdatareq ifdr; 1275 1.248 roy struct if_data *ifi; 1276 1.187 dyoung struct ifreq ifr; 1277 1.223 pooka struct ifdrv ifdrv; 1278 1.130 christos char fbuf[BUFSIZ]; 1279 1.228 pgoyette char *bp; 1280 1.187 dyoung int af, s; 1281 1.187 dyoung const char *ifname; 1282 1.187 dyoung struct ifcapreq ifcr; 1283 1.187 dyoung unsigned short flags; 1284 1.187 dyoung const struct afswtch *afp; 1285 1.239 ozaki char ifdescr[IFDESCRSIZE]; 1286 1.187 dyoung 1287 1.188 dyoung if ((af = getaf(env)) == -1) { 1288 1.188 dyoung afp = NULL; 1289 1.188 dyoung af = AF_UNSPEC; 1290 1.188 dyoung } else 1291 1.188 dyoung afp = lookup_af_bynum(af); 1292 1.188 dyoung 1293 1.201 dyoung /* get out early if the family is unsupported by the kernel */ 1294 1.188 dyoung if ((s = getsock(af)) == -1) 1295 1.187 dyoung err(EXIT_FAILURE, "%s: getsock", __func__); 1296 1.187 dyoung 1297 1.189 dyoung if ((ifname = getifinfo(env, oenv, &flags)) == NULL) 1298 1.187 dyoung err(EXIT_FAILURE, "%s: getifinfo", __func__); 1299 1.1 cgd 1300 1.235 ozaki (void)snprintb(fbuf, sizeof(fbuf), IFFBITS, flags); 1301 1.235 ozaki printf("%s: flags=%s", ifname, fbuf); 1302 1.187 dyoung 1303 1.187 dyoung estrlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1304 1.224 pooka if (prog_ioctl(s, SIOCGIFMETRIC, &ifr) == -1) 1305 1.187 dyoung warn("SIOCGIFMETRIC %s", ifr.ifr_name); 1306 1.187 dyoung else if (ifr.ifr_metric != 0) 1307 1.187 dyoung printf(" metric %d", ifr.ifr_metric); 1308 1.187 dyoung 1309 1.187 dyoung estrlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1310 1.224 pooka if (prog_ioctl(s, SIOCGIFMTU, &ifr) != -1 && ifr.ifr_mtu != 0) 1311 1.187 dyoung printf(" mtu %d", ifr.ifr_mtu); 1312 1.147 dsl printf("\n"); 1313 1.108 thorpej 1314 1.189 dyoung if (getifcaps(env, oenv, &ifcr) == -1) 1315 1.187 dyoung err(EXIT_FAILURE, "%s: getifcaps", __func__); 1316 1.187 dyoung 1317 1.187 dyoung if (ifcr.ifcr_capabilities != 0) { 1318 1.228 pgoyette (void)snprintb_m(fbuf, sizeof(fbuf), IFCAPBITS, 1319 1.228 pgoyette ifcr.ifcr_capabilities, MAX_PRINT_LEN); 1320 1.228 pgoyette bp = fbuf; 1321 1.228 pgoyette while (*bp != '\0') { 1322 1.241 ryo printf("\tcapabilities=%s\n", bp); 1323 1.228 pgoyette bp += strlen(bp) + 1; 1324 1.228 pgoyette } 1325 1.228 pgoyette (void)snprintb_m(fbuf, sizeof(fbuf), IFCAPBITS, 1326 1.228 pgoyette ifcr.ifcr_capenable, MAX_PRINT_LEN); 1327 1.228 pgoyette bp = fbuf; 1328 1.228 pgoyette while (*bp != '\0') { 1329 1.241 ryo printf("\tenabled=%s\n", bp); 1330 1.228 pgoyette bp += strlen(bp) + 1; 1331 1.228 pgoyette } 1332 1.108 thorpej } 1333 1.65 thorpej 1334 1.208 dyoung SIMPLEQ_FOREACH(status_f, &status_funcs, f_next) 1335 1.208 dyoung (*status_f->f_func)(env, oenv); 1336 1.65 thorpej 1337 1.239 ozaki estrlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 1338 1.239 ozaki ifr.ifr_buf = &ifdescr; 1339 1.239 ozaki ifr.ifr_buflen = sizeof(ifdescr); 1340 1.239 ozaki if (prog_ioctl(s, SIOCGIFDESCR, &ifr) == 0) 1341 1.239 ozaki printf("\tdescription: \"%s\"\n", (char *)ifr.ifr_buf); 1342 1.239 ozaki 1343 1.218 dyoung print_link_addresses(env, true); 1344 1.24 thorpej 1345 1.223 pooka estrlcpy(ifdrv.ifd_name, ifname, sizeof(ifdrv.ifd_name)); 1346 1.223 pooka ifdrv.ifd_cmd = IFLINKSTR_QUERYLEN; 1347 1.223 pooka ifdrv.ifd_len = 0; 1348 1.223 pooka ifdrv.ifd_data = NULL; 1349 1.223 pooka /* interface supports linkstr? */ 1350 1.224 pooka if (prog_ioctl(s, SIOCGLINKSTR, &ifdrv) != -1) { 1351 1.223 pooka char *p; 1352 1.223 pooka 1353 1.223 pooka p = malloc(ifdrv.ifd_len); 1354 1.223 pooka if (p == NULL) 1355 1.223 pooka err(EXIT_FAILURE, "malloc linkstr buf failed"); 1356 1.223 pooka ifdrv.ifd_data = p; 1357 1.223 pooka ifdrv.ifd_cmd = 0; 1358 1.224 pooka if (prog_ioctl(s, SIOCGLINKSTR, &ifdrv) == -1) 1359 1.223 pooka err(EXIT_FAILURE, "failed to query linkstr"); 1360 1.223 pooka printf("\tlinkstr: %s\n", (char *)ifdrv.ifd_data); 1361 1.223 pooka free(p); 1362 1.223 pooka } 1363 1.223 pooka 1364 1.251 ozaki if (vflag) 1365 1.251 ozaki printf("\tlinkstate: %s\n", link_state_str(link_state(env))); 1366 1.251 ozaki 1367 1.248 roy media_status(env, oenv); 1368 1.243 roy 1369 1.243 roy if (!vflag && !zflag) 1370 1.243 roy goto proto_status; 1371 1.243 roy 1372 1.246 roy /* We already have if_data from SIOCGIFDATA in ifa_data. */ 1373 1.248 roy estrlcpy(ifdr.ifdr_name, ifname, sizeof(ifdr.ifdr_name)); 1374 1.248 roy if (prog_ioctl(s, zflag ? SIOCZIFDATA : SIOCGIFDATA, &ifdr) == -1) 1375 1.248 roy err(EXIT_FAILURE, zflag ? "SIOCZIFDATA" : "SIOCGIFDATA"); 1376 1.248 roy ifi = &ifdr.ifdr_data; 1377 1.246 roy 1378 1.208 dyoung print_plural("\tinput: ", ifi->ifi_ipackets, "packet"); 1379 1.208 dyoung print_human_bytes(hflag, ifi->ifi_ibytes); 1380 1.208 dyoung if (ifi->ifi_imcasts) 1381 1.208 dyoung print_plural(", ", ifi->ifi_imcasts, "multicast"); 1382 1.208 dyoung if (ifi->ifi_ierrors) 1383 1.208 dyoung print_plural(", ", ifi->ifi_ierrors, "error"); 1384 1.208 dyoung if (ifi->ifi_iqdrops) 1385 1.208 dyoung print_plural(", ", ifi->ifi_iqdrops, "queue drop"); 1386 1.208 dyoung if (ifi->ifi_noproto) 1387 1.208 dyoung printf(", %" PRIu64 " unknown protocol", ifi->ifi_noproto); 1388 1.208 dyoung print_plural("\n\toutput: ", ifi->ifi_opackets, "packet"); 1389 1.208 dyoung print_human_bytes(hflag, ifi->ifi_obytes); 1390 1.208 dyoung if (ifi->ifi_omcasts) 1391 1.208 dyoung print_plural(", ", ifi->ifi_omcasts, "multicast"); 1392 1.208 dyoung if (ifi->ifi_oerrors) 1393 1.208 dyoung print_plural(", ", ifi->ifi_oerrors, "error"); 1394 1.208 dyoung if (ifi->ifi_collisions) 1395 1.208 dyoung print_plural(", ", ifi->ifi_collisions, "collision"); 1396 1.208 dyoung printf("\n"); 1397 1.124 matt 1398 1.208 dyoung SIMPLEQ_FOREACH(statistics_f, &statistics_funcs, f_next) 1399 1.208 dyoung (*statistics_f->f_func)(env); 1400 1.149 dyoung 1401 1.24 thorpej proto_status: 1402 1.187 dyoung 1403 1.187 dyoung if (afp != NULL) 1404 1.189 dyoung (*afp->af_status)(env, oenv, true); 1405 1.208 dyoung else SIMPLEQ_FOREACH(afp, &aflist, af_next) 1406 1.189 dyoung (*afp->af_status)(env, oenv, false); 1407 1.49 christos } 1408 1.49 christos 1409 1.208 dyoung static int 1410 1.211 dyoung setifprefixlen(prop_dictionary_t env, prop_dictionary_t oenv) 1411 1.53 itojun { 1412 1.189 dyoung bool rc; 1413 1.189 dyoung int64_t plen; 1414 1.187 dyoung int af; 1415 1.187 dyoung struct paddr_prefix *pfx; 1416 1.187 dyoung prop_data_t d; 1417 1.187 dyoung 1418 1.187 dyoung if ((af = getaf(env)) == -1) 1419 1.187 dyoung af = AF_INET; 1420 1.187 dyoung 1421 1.189 dyoung rc = prop_dictionary_get_int64(env, "prefixlen", &plen); 1422 1.189 dyoung assert(rc); 1423 1.187 dyoung 1424 1.189 dyoung pfx = prefixlen_to_mask(af, plen); 1425 1.187 dyoung if (pfx == NULL) 1426 1.187 dyoung err(EXIT_FAILURE, "prefixlen_to_mask"); 1427 1.187 dyoung 1428 1.242 thorpej d = prop_data_create_copy(pfx, paddr_prefix_size(pfx)); 1429 1.187 dyoung if (d == NULL) 1430 1.242 thorpej err(EXIT_FAILURE, "%s: prop_data_create_copy", __func__); 1431 1.187 dyoung 1432 1.211 dyoung if (!prop_dictionary_set(oenv, "netmask", (prop_object_t)d)) 1433 1.187 dyoung err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__); 1434 1.187 dyoung 1435 1.187 dyoung free(pfx); 1436 1.187 dyoung return 0; 1437 1.53 itojun } 1438 1.53 itojun 1439 1.223 pooka static int 1440 1.223 pooka setlinkstr(prop_dictionary_t env, prop_dictionary_t oenv) 1441 1.223 pooka { 1442 1.223 pooka struct ifdrv ifdrv; 1443 1.223 pooka size_t linkstrlen; 1444 1.223 pooka prop_data_t data; 1445 1.225 pooka char *linkstr; 1446 1.223 pooka 1447 1.223 pooka data = (prop_data_t)prop_dictionary_get(env, "linkstr"); 1448 1.223 pooka if (data == NULL) { 1449 1.223 pooka errno = ENOENT; 1450 1.223 pooka return -1; 1451 1.223 pooka } 1452 1.223 pooka linkstrlen = prop_data_size(data)+1; 1453 1.225 pooka 1454 1.225 pooka linkstr = malloc(linkstrlen); 1455 1.225 pooka if (linkstr == NULL) 1456 1.225 pooka err(EXIT_FAILURE, "malloc linkstr space"); 1457 1.225 pooka if (getargstr(env, "linkstr", linkstr, linkstrlen) == -1) 1458 1.225 pooka errx(EXIT_FAILURE, "getargstr linkstr failed"); 1459 1.223 pooka 1460 1.223 pooka ifdrv.ifd_cmd = 0; 1461 1.223 pooka ifdrv.ifd_len = linkstrlen; 1462 1.223 pooka ifdrv.ifd_data = __UNCONST(linkstr); 1463 1.223 pooka 1464 1.223 pooka if (direct_ioctl(env, SIOCSLINKSTR, &ifdrv) == -1) 1465 1.223 pooka err(EXIT_FAILURE, "SIOCSLINKSTR"); 1466 1.225 pooka free(linkstr); 1467 1.223 pooka 1468 1.223 pooka return 0; 1469 1.223 pooka } 1470 1.223 pooka 1471 1.223 pooka static int 1472 1.223 pooka unsetlinkstr(prop_dictionary_t env, prop_dictionary_t oenv) 1473 1.223 pooka { 1474 1.223 pooka struct ifdrv ifdrv; 1475 1.223 pooka 1476 1.223 pooka memset(&ifdrv, 0, sizeof(ifdrv)); 1477 1.223 pooka ifdrv.ifd_cmd = IFLINKSTR_UNSET; 1478 1.223 pooka 1479 1.223 pooka if (direct_ioctl(env, SIOCSLINKSTR, &ifdrv) == -1) 1480 1.223 pooka err(EXIT_FAILURE, "SIOCSLINKSTR"); 1481 1.223 pooka 1482 1.223 pooka return 0; 1483 1.223 pooka } 1484 1.223 pooka 1485 1.239 ozaki static int 1486 1.239 ozaki setifdescr(prop_dictionary_t env, prop_dictionary_t oenv) 1487 1.239 ozaki { 1488 1.239 ozaki struct ifreq ifr; 1489 1.239 ozaki size_t len; 1490 1.239 ozaki prop_data_t data; 1491 1.239 ozaki char *descr; 1492 1.239 ozaki 1493 1.240 msaitoh data = (prop_data_t)prop_dictionary_get(env, "descr"); 1494 1.239 ozaki if (data == NULL) { 1495 1.239 ozaki errno = ENOENT; 1496 1.239 ozaki return -1; 1497 1.239 ozaki } 1498 1.239 ozaki len = prop_data_size(data) + 1; 1499 1.239 ozaki 1500 1.240 msaitoh if (len > IFDESCRSIZE) 1501 1.239 ozaki err(EXIT_FAILURE, "description too long"); 1502 1.239 ozaki 1503 1.240 msaitoh descr = malloc(len); 1504 1.239 ozaki if (descr == NULL) 1505 1.239 ozaki err(EXIT_FAILURE, "malloc description space"); 1506 1.239 ozaki if (getargstr(env, "descr", descr, len) == -1) 1507 1.239 ozaki errx(EXIT_FAILURE, "getargstr descr failed"); 1508 1.239 ozaki 1509 1.239 ozaki 1510 1.240 msaitoh ifr.ifr_buf = descr; 1511 1.239 ozaki ifr.ifr_buflen = len; 1512 1.239 ozaki if (direct_ioctl(env, SIOCSIFDESCR, &ifr) != 0) 1513 1.239 ozaki err(EXIT_FAILURE, "SIOCSIFDESCR"); 1514 1.239 ozaki 1515 1.240 msaitoh free(descr); 1516 1.239 ozaki 1517 1.240 msaitoh return 0; 1518 1.239 ozaki } 1519 1.239 ozaki 1520 1.239 ozaki static int 1521 1.239 ozaki unsetifdescr(prop_dictionary_t env, prop_dictionary_t oenv) 1522 1.239 ozaki { 1523 1.239 ozaki struct ifreq ifr; 1524 1.239 ozaki ifr.ifr_buf = NULL; 1525 1.239 ozaki ifr.ifr_buflen = 0; 1526 1.239 ozaki 1527 1.240 msaitoh if (direct_ioctl(env, SIOCSIFDESCR, &ifr) != 0) 1528 1.239 ozaki err(EXIT_FAILURE, "SIOCSIFDESCR"); 1529 1.239 ozaki 1530 1.240 msaitoh return 0; 1531 1.239 ozaki } 1532 1.239 ozaki 1533 1.239 ozaki 1534 1.210 dyoung static void 1535 1.145 dsl usage(void) 1536 1.18 glass { 1537 1.99 cgd const char *progname = getprogname(); 1538 1.209 dyoung usage_func_t *usage_f; 1539 1.209 dyoung prop_dictionary_t env; 1540 1.80 thorpej 1541 1.209 dyoung if ((env = prop_dictionary_create()) == NULL) 1542 1.209 dyoung err(EXIT_FAILURE, "%s: prop_dictionary_create", __func__); 1543 1.209 dyoung 1544 1.209 dyoung fprintf(stderr, "usage: %s [-h] %s[-v] [-z] %sinterface\n" 1545 1.105 itojun "\t[ af [ address [ dest_addr ] ] [ netmask mask ] [ prefixlen n ]\n" 1546 1.105 itojun "\t\t[ alias | -alias ] ]\n" 1547 1.209 dyoung "\t[ up ] [ down ] [ metric n ] [ mtu n ]\n", progname, 1548 1.209 dyoung flag_is_registered(gflags, 'm') ? "[-m] " : "", 1549 1.209 dyoung flag_is_registered(gflags, 'L') ? "[-L] " : ""); 1550 1.209 dyoung 1551 1.209 dyoung SIMPLEQ_FOREACH(usage_f, &usage_funcs, f_next) 1552 1.209 dyoung (*usage_f->f_func)(env); 1553 1.209 dyoung 1554 1.209 dyoung fprintf(stderr, 1555 1.80 thorpej "\t[ arp | -arp ]\n" 1556 1.178 dyoung "\t[ preference n ]\n" 1557 1.80 thorpej "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ]\n" 1558 1.237 ozaki "\t[ linkstr str | -linkstr ]\n" 1559 1.249 knakahar "\t[ unnumbered | -unnumbered ]\n" 1560 1.239 ozaki "\t[ description str | descr str | -description | -descr ]\n" 1561 1.209 dyoung " %s -a [-b] [-d] [-h] %s[-u] [-v] [-z] [ af ]\n" 1562 1.209 dyoung " %s -l [-b] [-d] [-s] [-u]\n" 1563 1.101 christos " %s -C\n" 1564 1.232 roy " %s -w n\n" 1565 1.81 thorpej " %s interface create\n" 1566 1.81 thorpej " %s interface destroy\n", 1567 1.209 dyoung progname, flag_is_registered(gflags, 'm') ? "[-m] " : "", 1568 1.232 roy progname, progname, progname, progname, progname); 1569 1.209 dyoung 1570 1.209 dyoung prop_object_release((prop_object_t)env); 1571 1.187 dyoung exit(EXIT_FAILURE); 1572 1.1 cgd } 1573