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