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