File: | src/sbin/ifconfig/ifconfig.c |
Warning: | line 1205, column 3 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ifconfig.c,v 1.470 2023/11/23 03:38:34 dlg Exp $ */ | |||
2 | /* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Copyright (c) 1983, 1993 | |||
6 | * The Regents of the University of California. All rights reserved. | |||
7 | * | |||
8 | * Redistribution and use in source and binary forms, with or without | |||
9 | * modification, are permitted provided that the following conditions | |||
10 | * are met: | |||
11 | * 1. Redistributions of source code must retain the above copyright | |||
12 | * notice, this list of conditions and the following disclaimer. | |||
13 | * 2. Redistributions in binary form must reproduce the above copyright | |||
14 | * notice, this list of conditions and the following disclaimer in the | |||
15 | * documentation and/or other materials provided with the distribution. | |||
16 | * 3. Neither the name of the University nor the names of its contributors | |||
17 | * may be used to endorse or promote products derived from this software | |||
18 | * without specific prior written permission. | |||
19 | * | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |||
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |||
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
30 | * SUCH DAMAGE. | |||
31 | */ | |||
32 | ||||
33 | /*- | |||
34 | * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. | |||
35 | * All rights reserved. | |||
36 | * | |||
37 | * This code is derived from software contributed to The NetBSD Foundation | |||
38 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |||
39 | * NASA Ames Research Center. | |||
40 | * | |||
41 | * Redistribution and use in source and binary forms, with or without | |||
42 | * modification, are permitted provided that the following conditions | |||
43 | * are met: | |||
44 | * 1. Redistributions of source code must retain the above copyright | |||
45 | * notice, this list of conditions and the following disclaimer. | |||
46 | * 2. Redistributions in binary form must reproduce the above copyright | |||
47 | * notice, this list of conditions and the following disclaimer in the | |||
48 | * documentation and/or other materials provided with the distribution. | |||
49 | * | |||
50 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||
51 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
52 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
53 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |||
54 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
55 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
56 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
57 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
58 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
59 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
60 | * POSSIBILITY OF SUCH DAMAGE. | |||
61 | */ | |||
62 | ||||
63 | #include <sys/socket.h> | |||
64 | #include <sys/ioctl.h> | |||
65 | #include <sys/time.h> | |||
66 | ||||
67 | #include <net/if.h> | |||
68 | #include <net/if_dl.h> | |||
69 | #include <net/if_media.h> | |||
70 | #include <net/if_types.h> | |||
71 | #include <netinet/in.h> | |||
72 | #include <netinet/in_var.h> | |||
73 | #include <netinet6/in6_var.h> | |||
74 | #include <netinet6/nd6.h> | |||
75 | #include <arpa/inet.h> | |||
76 | #include <netinet/ip_ipsp.h> | |||
77 | #include <netinet/if_ether.h> | |||
78 | #include <net80211/ieee80211.h> | |||
79 | #include <net80211/ieee80211_ioctl.h> | |||
80 | #include <net/pfvar.h> | |||
81 | #include <net/if_pfsync.h> | |||
82 | #include <net/if_pflow.h> | |||
83 | #include <net/if_pppoe.h> | |||
84 | #include <net/if_trunk.h> | |||
85 | #include <net/if_wg.h> | |||
86 | #include <net/trunklacp.h> | |||
87 | #include <net/if_sppp.h> | |||
88 | #include <net/ppp_defs.h> | |||
89 | ||||
90 | #include <netinet/ip_carp.h> | |||
91 | ||||
92 | #include <netdb.h> | |||
93 | ||||
94 | #include <net/if_vlan_var.h> | |||
95 | ||||
96 | #include <netmpls/mpls.h> | |||
97 | ||||
98 | #include <ctype.h> | |||
99 | #include <err.h> | |||
100 | #include <errno(*__errno()).h> | |||
101 | #include <stdio.h> | |||
102 | #include <stdint.h> | |||
103 | #include <stdlib.h> | |||
104 | #include <stddef.h> | |||
105 | #include <string.h> | |||
106 | #include <unistd.h> | |||
107 | #include <limits.h> | |||
108 | #include <resolv.h> | |||
109 | #include <util.h> | |||
110 | #include <ifaddrs.h> | |||
111 | ||||
112 | #ifndef SMALL | |||
113 | #include <dev/usb/mbim.h> | |||
114 | #include <dev/usb/if_umb.h> | |||
115 | #endif /* SMALL */ | |||
116 | ||||
117 | #include "ifconfig.h" | |||
118 | ||||
119 | #ifndef nitems | |||
120 | #define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0])) | |||
121 | #endif | |||
122 | ||||
123 | #define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b)) | |||
124 | #define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b)) | |||
125 | ||||
126 | #define HWFEATURESBITS"\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6" "\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL" \ | |||
127 | "\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" \ | |||
128 | "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6" \ | |||
129 | "\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL" | |||
130 | ||||
131 | struct ifencap { | |||
132 | unsigned int ife_flags; | |||
133 | #define IFE_VNETID_MASK0xf 0xf | |||
134 | #define IFE_VNETID_NOPE0x0 0x0 | |||
135 | #define IFE_VNETID_NONE0x1 0x1 | |||
136 | #define IFE_VNETID_ANY0x2 0x2 | |||
137 | #define IFE_VNETID_SET0x3 0x3 | |||
138 | int64_t ife_vnetid; | |||
139 | #define IFE_VNETFLOWID0x10 0x10 | |||
140 | ||||
141 | #define IFE_PARENT_MASK0xf00 0xf00 | |||
142 | #define IFE_PARENT_NOPE0x000 0x000 | |||
143 | #define IFE_PARENT_NONE0x100 0x100 | |||
144 | #define IFE_PARENT_SET0x200 0x200 | |||
145 | char ife_parent[IFNAMSIZ16]; | |||
146 | ||||
147 | #define IFE_TXHPRIO_SET0x1000 0x1000 | |||
148 | int ife_txhprio; | |||
149 | #define IFE_RXHPRIO_SET0x2000 0x2000 | |||
150 | int ife_rxhprio; | |||
151 | }; | |||
152 | ||||
153 | struct ifreq ifr, ridreq; | |||
154 | struct in_aliasreq in_addreq; | |||
155 | struct in6_ifreq ifr6; | |||
156 | struct in6_ifreq in6_ridreq; | |||
157 | struct in6_aliasreq in6_addreq; | |||
158 | struct sockaddr_in netmask; | |||
159 | ||||
160 | #ifndef SMALL | |||
161 | int rdomainid; | |||
162 | #endif /* SMALL */ | |||
163 | ||||
164 | char ifname[IFNAMSIZ16]; | |||
165 | int flags, xflags, setaddr, setipdst, doalias; | |||
166 | u_long metric, mtu; | |||
167 | int llprio; | |||
168 | int clearaddr, sock; | |||
169 | int newaddr = 0; | |||
170 | int af = AF_INET2; | |||
171 | int explicit_prefix = 0; | |||
172 | int Lflag = 1; | |||
173 | int show_join = 0; | |||
174 | ||||
175 | int showmediaflag; | |||
176 | int showcapsflag; | |||
177 | int shownet80211chans; | |||
178 | int shownet80211nodes; | |||
179 | int showclasses; | |||
180 | int showtransceiver; | |||
181 | ||||
182 | struct ifencap; | |||
183 | ||||
184 | struct ieee80211_join join; | |||
185 | ||||
186 | const char *lacpmodeactive = "active"; | |||
187 | const char *lacpmodepassive = "passive"; | |||
188 | const char *lacptimeoutfast = "fast"; | |||
189 | const char *lacptimeoutslow = "slow"; | |||
190 | ||||
191 | void notealias(const char *, int); | |||
192 | void setifaddr(const char *, int); | |||
193 | void setiflladdr(const char *, int); | |||
194 | void setifdstaddr(const char *, int); | |||
195 | void setifflags(const char *, int); | |||
196 | void setifxflags(const char *, int); | |||
197 | void addaf(const char *, int); | |||
198 | void removeaf(const char *, int); | |||
199 | void setifbroadaddr(const char *, int); | |||
200 | void setifmtu(const char *, int); | |||
201 | void setifllprio(const char *, int); | |||
202 | void setifnwid(const char *, int); | |||
203 | void setifjoin(const char *, int); | |||
204 | void delifjoin(const char *, int); | |||
205 | void delifjoinlist(const char *, int); | |||
206 | void showjoin(const char *, int); | |||
207 | void setifbssid(const char *, int); | |||
208 | void setifnwkey(const char *, int); | |||
209 | void setifwpa(const char *, int); | |||
210 | void setifwpaprotos(const char *, int); | |||
211 | void setifwpaakms(const char *, int); | |||
212 | void setifwpaciphers(const char *, int); | |||
213 | void setifwpagroupcipher(const char *, int); | |||
214 | void setifwpakey(const char *, int); | |||
215 | void setifchan(const char *, int); | |||
216 | void setifscan(const char *, int); | |||
217 | void setifnwflag(const char *, int); | |||
218 | void unsetifnwflag(const char *, int); | |||
219 | void setifnetmask(const char *, int); | |||
220 | void setifprefixlen(const char *, int); | |||
221 | void setvnetid(const char *, int); | |||
222 | void delvnetid(const char *, int); | |||
223 | void getvnetid(struct ifencap *); | |||
224 | void setifparent(const char *, int); | |||
225 | void delifparent(const char *, int); | |||
226 | void getifparent(struct ifencap *); | |||
227 | void getencap(void); | |||
228 | void setia6flags(const char *, int); | |||
229 | void setia6pltime(const char *, int); | |||
230 | void setia6vltime(const char *, int); | |||
231 | void setia6lifetime(const char *, const char *); | |||
232 | void setia6eui64(const char *, int); | |||
233 | void setmedia(const char *, int); | |||
234 | void setmediaopt(const char *, int); | |||
235 | void setmediamode(const char *, int); | |||
236 | void unsetmediamode(const char *, int); | |||
237 | void clone_create(const char *, int); | |||
238 | void clone_destroy(const char *, int); | |||
239 | void unsetmediaopt(const char *, int); | |||
240 | void setmediainst(const char *, int); | |||
241 | int prefix(void *val, int); | |||
242 | void getifgroups(void); | |||
243 | void setifgroup(const char *, int); | |||
244 | void unsetifgroup(const char *, int); | |||
245 | void setgroupattribs(char *, int, char *[]); | |||
246 | int printgroup(char *, int); | |||
247 | void setautoconf(const char *, int); | |||
248 | void settemporary(const char *, int); | |||
249 | void settrunkport(const char *, int); | |||
250 | void unsettrunkport(const char *, int); | |||
251 | void settrunkproto(const char *, int); | |||
252 | void settrunklacpmode(const char *, int); | |||
253 | void settrunklacptimeout(const char *, int); | |||
254 | void trunk_status(void); | |||
255 | void list_cloners(void); | |||
256 | ||||
257 | #ifndef SMALL | |||
258 | void setifrtlabel(const char *, int); | |||
259 | void setrdomain(const char *, int); | |||
260 | void unsetrdomain(const char *, int); | |||
261 | void setkeepalive(const char *, const char *); | |||
262 | void unsetkeepalive(const char *, int); | |||
263 | void carp_status(void); | |||
264 | void setcarp_advbase(const char *,int); | |||
265 | void setcarp_advskew(const char *, int); | |||
266 | void setcarppeer(const char *, int); | |||
267 | void unsetcarppeer(const char *, int); | |||
268 | void setcarp_passwd(const char *, int); | |||
269 | void setcarp_vhid(const char *, int); | |||
270 | void setcarp_state(const char *, int); | |||
271 | void setcarpdev(const char *, int); | |||
272 | void setcarp_nodes(const char *, int); | |||
273 | void setcarp_balancing(const char *, int); | |||
274 | void setpfsync_syncdev(const char *, int); | |||
275 | void setpfsync_maxupd(const char *, int); | |||
276 | void unsetpfsync_syncdev(const char *, int); | |||
277 | void setpfsync_syncpeer(const char *, int); | |||
278 | void unsetpfsync_syncpeer(const char *, int); | |||
279 | void setpfsync_defer(const char *, int); | |||
280 | void pfsync_status(void); | |||
281 | void setvnetflowid(const char *, int); | |||
282 | void delvnetflowid(const char *, int); | |||
283 | void getvnetflowid(struct ifencap *); | |||
284 | void gettxprio(struct ifencap *); | |||
285 | void settxprio(const char *, int); | |||
286 | void getrxprio(struct ifencap *); | |||
287 | void setrxprio(const char *, int); | |||
288 | void setmplslabel(const char *, int); | |||
289 | void unsetmplslabel(const char *, int); | |||
290 | void setpwe3cw(const char *, int); | |||
291 | void unsetpwe3cw(const char *, int); | |||
292 | void setpwe3fat(const char *, int); | |||
293 | void unsetpwe3fat(const char *, int); | |||
294 | void setpwe3neighbor(const char *, const char *); | |||
295 | void unsetpwe3neighbor(const char *, int); | |||
296 | void mpls_status(void); | |||
297 | void settunnel(const char *, const char *); | |||
298 | void settunneladdr(const char *, int); | |||
299 | void deletetunnel(const char *, int); | |||
300 | void settunnelinst(const char *, int); | |||
301 | void unsettunnelinst(const char *, int); | |||
302 | void settunnelttl(const char *, int); | |||
303 | void settunneldf(const char *, int); | |||
304 | void settunnelnodf(const char *, int); | |||
305 | void settunnelecn(const char *, int); | |||
306 | void settunnelnoecn(const char *, int); | |||
307 | void setpppoe_dev(const char *,int); | |||
308 | void setpppoe_svc(const char *,int); | |||
309 | void setpppoe_ac(const char *,int); | |||
310 | void pppoe_status(void); | |||
311 | void setspppproto(const char *, int); | |||
312 | void setspppname(const char *, int); | |||
313 | void setspppkey(const char *, int); | |||
314 | void setsppppeerproto(const char *, int); | |||
315 | void setsppppeername(const char *, int); | |||
316 | void setsppppeerkey(const char *, int); | |||
317 | void setsppppeerflag(const char *, int); | |||
318 | void unsetsppppeerflag(const char *, int); | |||
319 | void sppp_status(void); | |||
320 | void sppp_printproto(const char *, struct sauthreq *); | |||
321 | void setifpriority(const char *, int); | |||
322 | void setifpowersave(const char *, int); | |||
323 | void setifmetric(const char *, int); | |||
324 | void pflow_status(void); | |||
325 | void pflow_addr(const char*, struct sockaddr_storage *); | |||
326 | void setpflow_sender(const char *, int); | |||
327 | void unsetpflow_sender(const char *, int); | |||
328 | void setpflow_receiver(const char *, int); | |||
329 | void unsetpflow_receiver(const char *, int); | |||
330 | void setpflowproto(const char *, int); | |||
331 | void setifipdst(const char *, int); | |||
332 | void setifdesc(const char *, int); | |||
333 | void unsetifdesc(const char *, int); | |||
334 | void printifhwfeatures(const char *, int); | |||
335 | void setpair(const char *, int); | |||
336 | void unsetpair(const char *, int); | |||
337 | void umb_status(void); | |||
338 | void umb_printclasses(char *, int); | |||
339 | int umb_parse_classes(const char *); | |||
340 | void umb_setpin(const char *, int); | |||
341 | void umb_chgpin(const char *, const char *); | |||
342 | void umb_puk(const char *, const char *); | |||
343 | void umb_pinop(int, int, const char *, const char *); | |||
344 | void umb_apn(const char *, int); | |||
345 | void umb_setclass(const char *, int); | |||
346 | void umb_roaming(const char *, int); | |||
347 | void utf16_to_char(uint16_t *, int, char *, size_t); | |||
348 | int char_to_utf16(const char *, uint16_t *, size_t); | |||
349 | void transceiver(const char *, int); | |||
350 | void transceiverdump(const char *, int); | |||
351 | ||||
352 | /* WG */ | |||
353 | void setwgpeer(const char *, int); | |||
354 | void setwgpeerdesc(const char *, int); | |||
355 | void setwgpeerep(const char *, const char *); | |||
356 | void setwgpeeraip(const char *, int); | |||
357 | void setwgpeerpsk(const char *, int); | |||
358 | void setwgpeerpka(const char *, int); | |||
359 | void setwgport(const char *, int); | |||
360 | void setwgkey(const char *, int); | |||
361 | void setwgrtable(const char *, int); | |||
362 | ||||
363 | void unsetwgpeer(const char *, int); | |||
364 | void unsetwgpeerdesc(const char *, int); | |||
365 | void unsetwgpeerpsk(const char *, int); | |||
366 | void unsetwgpeerall(const char *, int); | |||
367 | ||||
368 | void wg_status(int); | |||
369 | #else | |||
370 | void setignore(const char *, int); | |||
371 | #endif | |||
372 | ||||
373 | struct if_clonereq *get_cloners(void); | |||
374 | int findmac(const char *); | |||
375 | ||||
376 | /* | |||
377 | * Media stuff. Whenever a media command is first performed, the | |||
378 | * currently select media is grabbed for this interface. If `media' | |||
379 | * is given, the current media word is modified. `mediaopt' commands | |||
380 | * only modify the set and clear words. They then operate on the | |||
381 | * current media word later. | |||
382 | */ | |||
383 | uint64_t media_current; | |||
384 | uint64_t mediaopt_set; | |||
385 | uint64_t mediaopt_clear; | |||
386 | ||||
387 | int actions; /* Actions performed */ | |||
388 | ||||
389 | #define A_MEDIA0x0001 0x0001 /* media command */ | |||
390 | #define A_MEDIAOPTSET0x0002 0x0002 /* mediaopt command */ | |||
391 | #define A_MEDIAOPTCLR0x0004 0x0004 /* -mediaopt command */ | |||
392 | #define A_MEDIAOPT(0x0002|0x0004) (A_MEDIAOPTSET0x0002|A_MEDIAOPTCLR0x0004) | |||
393 | #define A_MEDIAINST0x0008 0x0008 /* instance or inst command */ | |||
394 | #define A_MEDIAMODE0x0010 0x0010 /* mode command */ | |||
395 | #define A_JOIN0x0020 0x0020 /* join */ | |||
396 | #define A_WIREGUARD0x0040 0x0040 /* any WireGuard command */ | |||
397 | #define A_SILENT0x8000000 0x8000000 /* doing operation, do not print */ | |||
398 | ||||
399 | #define NEXTARG00xffffff 0xffffff | |||
400 | #define NEXTARG0xfffffe 0xfffffe | |||
401 | #define NEXTARG20xfffffd 0xfffffd | |||
402 | ||||
403 | const struct cmd { | |||
404 | char *c_name; | |||
405 | int c_parameter; /* NEXTARG means next argv */ | |||
406 | int c_action; /* defered action */ | |||
407 | void (*c_func)(const char *, int); | |||
408 | void (*c_func2)(const char *, const char *); | |||
409 | } cmds[] = { | |||
410 | { "up", IFF_UP0x1, 0, setifflags } , | |||
411 | { "down", -IFF_UP0x1, 0, setifflags }, | |||
412 | { "arp", -IFF_NOARP0x80, 0, setifflags }, | |||
413 | { "-arp", IFF_NOARP0x80, 0, setifflags }, | |||
414 | { "debug", IFF_DEBUG0x4, 0, setifflags }, | |||
415 | { "-debug", -IFF_DEBUG0x4, 0, setifflags }, | |||
416 | { "alias", IFF_UP0x1, 0, notealias }, | |||
417 | { "-alias", -IFF_UP0x1, 0, notealias }, | |||
418 | { "delete", -IFF_UP0x1, 0, notealias }, | |||
419 | { "netmask", NEXTARG0xfffffe, 0, setifnetmask }, | |||
420 | { "mtu", NEXTARG0xfffffe, 0, setifmtu }, | |||
421 | { "nwid", NEXTARG0xfffffe, 0, setifnwid }, | |||
422 | { "-nwid", -1, 0, setifnwid }, | |||
423 | { "join", NEXTARG0xfffffe, 0, setifjoin }, | |||
424 | { "-join", NEXTARG0xfffffe, 0, delifjoin }, | |||
425 | { "joinlist", NEXTARG00xffffff, 0, showjoin }, | |||
426 | { "-joinlist", -1, 0, delifjoinlist }, | |||
427 | { "bssid", NEXTARG0xfffffe, 0, setifbssid }, | |||
428 | { "-bssid", -1, 0, setifbssid }, | |||
429 | { "nwkey", NEXTARG0xfffffe, 0, setifnwkey }, | |||
430 | { "-nwkey", -1, 0, setifnwkey }, | |||
431 | { "wpa", 1, 0, setifwpa }, | |||
432 | { "-wpa", 0, 0, setifwpa }, | |||
433 | { "wpaakms", NEXTARG0xfffffe, 0, setifwpaakms }, | |||
434 | { "wpaciphers", NEXTARG0xfffffe, 0, setifwpaciphers }, | |||
435 | { "wpagroupcipher", NEXTARG0xfffffe, 0, setifwpagroupcipher }, | |||
436 | { "wpaprotos", NEXTARG0xfffffe, 0, setifwpaprotos }, | |||
437 | { "wpakey", NEXTARG0xfffffe, 0, setifwpakey }, | |||
438 | { "-wpakey", -1, 0, setifwpakey }, | |||
439 | { "chan", NEXTARG00xffffff, 0, setifchan }, | |||
440 | { "-chan", -1, 0, setifchan }, | |||
441 | { "scan", NEXTARG00xffffff, 0, setifscan }, | |||
442 | { "broadcast", NEXTARG0xfffffe, 0, setifbroadaddr }, | |||
443 | { "prefixlen", NEXTARG0xfffffe, 0, setifprefixlen}, | |||
444 | { "vnetid", NEXTARG0xfffffe, 0, setvnetid }, | |||
445 | { "-vnetid", 0, 0, delvnetid }, | |||
446 | { "parent", NEXTARG0xfffffe, 0, setifparent }, | |||
447 | { "-parent", 1, 0, delifparent }, | |||
448 | { "vlan", NEXTARG0xfffffe, 0, setvnetid }, | |||
449 | { "-vlan", 0, 0, delvnetid }, | |||
450 | { "vlandev", NEXTARG0xfffffe, 0, setifparent }, | |||
451 | { "-vlandev", 1, 0, delifparent }, | |||
452 | { "group", NEXTARG0xfffffe, 0, setifgroup }, | |||
453 | { "-group", NEXTARG0xfffffe, 0, unsetifgroup }, | |||
454 | { "autoconf", 1, 0, setautoconf }, | |||
455 | { "-autoconf", -1, 0, setautoconf }, | |||
456 | { "trunkport", NEXTARG0xfffffe, 0, settrunkport }, | |||
457 | { "-trunkport", NEXTARG0xfffffe, 0, unsettrunkport }, | |||
458 | { "trunkproto", NEXTARG0xfffffe, 0, settrunkproto }, | |||
459 | { "lacpmode", NEXTARG0xfffffe, 0, settrunklacpmode }, | |||
460 | { "lacptimeout", NEXTARG0xfffffe, 0, settrunklacptimeout }, | |||
461 | { "anycast", IN6_IFF_ANYCAST0x01, 0, setia6flags }, | |||
462 | { "-anycast", -IN6_IFF_ANYCAST0x01, 0, setia6flags }, | |||
463 | { "tentative", IN6_IFF_TENTATIVE0x02, 0, setia6flags }, | |||
464 | { "-tentative", -IN6_IFF_TENTATIVE0x02, 0, setia6flags }, | |||
465 | { "pltime", NEXTARG0xfffffe, 0, setia6pltime }, | |||
466 | { "vltime", NEXTARG0xfffffe, 0, setia6vltime }, | |||
467 | { "eui64", 0, 0, setia6eui64 }, | |||
468 | { "temporary", 1, 0, settemporary }, | |||
469 | { "-temporary", -1, 0, settemporary }, | |||
470 | { "soii", -IFXF_INET6_NOSOII0x40, 0, setifxflags }, | |||
471 | { "-soii", IFXF_INET6_NOSOII0x40, 0, setifxflags }, | |||
472 | { "monitor", IFXF_MONITOR0x100, 0, setifxflags }, | |||
473 | { "-monitor", -IFXF_MONITOR0x100, 0, setifxflags }, | |||
474 | { "tcplro", IFXF_LRO0x200, 0, setifxflags }, | |||
475 | { "-tcplro", -IFXF_LRO0x200, 0, setifxflags }, | |||
476 | #ifndef SMALL | |||
477 | { "hwfeatures", NEXTARG00xffffff, 0, printifhwfeatures }, | |||
478 | { "metric", NEXTARG0xfffffe, 0, setifmetric }, | |||
479 | { "powersave", NEXTARG00xffffff, 0, setifpowersave }, | |||
480 | { "-powersave", -1, 0, setifpowersave }, | |||
481 | { "priority", NEXTARG0xfffffe, 0, setifpriority }, | |||
482 | { "rtlabel", NEXTARG0xfffffe, 0, setifrtlabel }, | |||
483 | { "-rtlabel", -1, 0, setifrtlabel }, | |||
484 | { "rdomain", NEXTARG0xfffffe, 0, setrdomain }, | |||
485 | { "-rdomain", 0, 0, unsetrdomain }, | |||
486 | { "staticarp", IFF_STATICARP0x20, 0, setifflags }, | |||
487 | { "-staticarp", -IFF_STATICARP0x20, 0, setifflags }, | |||
488 | { "mpls", IFXF_MPLS0x8, 0, setifxflags }, | |||
489 | { "-mpls", -IFXF_MPLS0x8, 0, setifxflags }, | |||
490 | { "mplslabel", NEXTARG0xfffffe, 0, setmplslabel }, | |||
491 | { "-mplslabel", 0, 0, unsetmplslabel }, | |||
492 | { "pwecw", 0, 0, setpwe3cw }, | |||
493 | { "-pwecw", 0, 0, unsetpwe3cw }, | |||
494 | { "pwefat", 0, 0, setpwe3fat }, | |||
495 | { "-pwefat", 0, 0, unsetpwe3fat }, | |||
496 | { "pweneighbor", NEXTARG20xfffffd, 0, NULL((void *)0), setpwe3neighbor }, | |||
497 | { "-pweneighbor", 0, 0, unsetpwe3neighbor }, | |||
498 | { "advbase", NEXTARG0xfffffe, 0, setcarp_advbase }, | |||
499 | { "advskew", NEXTARG0xfffffe, 0, setcarp_advskew }, | |||
500 | { "carppeer", NEXTARG0xfffffe, 0, setcarppeer }, | |||
501 | { "-carppeer", 1, 0, unsetcarppeer }, | |||
502 | { "pass", NEXTARG0xfffffe, 0, setcarp_passwd }, | |||
503 | { "vhid", NEXTARG0xfffffe, 0, setcarp_vhid }, | |||
504 | { "state", NEXTARG0xfffffe, 0, setcarp_state }, | |||
505 | { "carpdev", NEXTARG0xfffffe, 0, setcarpdev }, | |||
506 | { "carpnodes", NEXTARG0xfffffe, 0, setcarp_nodes }, | |||
507 | { "balancing", NEXTARG0xfffffe, 0, setcarp_balancing }, | |||
508 | { "syncdev", NEXTARG0xfffffe, 0, setpfsync_syncdev }, | |||
509 | { "-syncdev", 1, 0, unsetpfsync_syncdev }, | |||
510 | { "syncif", NEXTARG0xfffffe, 0, setpfsync_syncdev }, | |||
511 | { "-syncif", 1, 0, unsetpfsync_syncdev }, | |||
512 | { "syncpeer", NEXTARG0xfffffe, 0, setpfsync_syncpeer }, | |||
513 | { "-syncpeer", 1, 0, unsetpfsync_syncpeer }, | |||
514 | { "maxupd", NEXTARG0xfffffe, 0, setpfsync_maxupd }, | |||
515 | { "defer", 1, 0, setpfsync_defer }, | |||
516 | { "-defer", 0, 0, setpfsync_defer }, | |||
517 | { "tunnel", NEXTARG20xfffffd, 0, NULL((void *)0), settunnel }, | |||
518 | { "tunneladdr", NEXTARG0xfffffe, 0, settunneladdr }, | |||
519 | { "-tunnel", 0, 0, deletetunnel }, | |||
520 | { "tunneldomain", NEXTARG0xfffffe, 0, settunnelinst }, | |||
521 | { "-tunneldomain", 0, 0, unsettunnelinst }, | |||
522 | { "tunnelttl", NEXTARG0xfffffe, 0, settunnelttl }, | |||
523 | { "tunneldf", 0, 0, settunneldf }, | |||
524 | { "-tunneldf", 0, 0, settunnelnodf }, | |||
525 | { "tunnelecn", 0, 0, settunnelecn }, | |||
526 | { "-tunnelecn", 0, 0, settunnelnoecn }, | |||
527 | { "vnetflowid", 0, 0, setvnetflowid }, | |||
528 | { "-vnetflowid", 0, 0, delvnetflowid }, | |||
529 | { "txprio", NEXTARG0xfffffe, 0, settxprio }, | |||
530 | { "rxprio", NEXTARG0xfffffe, 0, setrxprio }, | |||
531 | { "pppoedev", NEXTARG0xfffffe, 0, setpppoe_dev }, | |||
532 | { "pppoesvc", NEXTARG0xfffffe, 0, setpppoe_svc }, | |||
533 | { "-pppoesvc", 1, 0, setpppoe_svc }, | |||
534 | { "pppoeac", NEXTARG0xfffffe, 0, setpppoe_ac }, | |||
535 | { "-pppoeac", 1, 0, setpppoe_ac }, | |||
536 | { "authproto", NEXTARG0xfffffe, 0, setspppproto }, | |||
537 | { "authname", NEXTARG0xfffffe, 0, setspppname }, | |||
538 | { "authkey", NEXTARG0xfffffe, 0, setspppkey }, | |||
539 | { "peerproto", NEXTARG0xfffffe, 0, setsppppeerproto }, | |||
540 | { "peername", NEXTARG0xfffffe, 0, setsppppeername }, | |||
541 | { "peerkey", NEXTARG0xfffffe, 0, setsppppeerkey }, | |||
542 | { "peerflag", NEXTARG0xfffffe, 0, setsppppeerflag }, | |||
543 | { "-peerflag", NEXTARG0xfffffe, 0, unsetsppppeerflag }, | |||
544 | { "nwflag", NEXTARG0xfffffe, 0, setifnwflag }, | |||
545 | { "-nwflag", NEXTARG0xfffffe, 0, unsetifnwflag }, | |||
546 | { "flowsrc", NEXTARG0xfffffe, 0, setpflow_sender }, | |||
547 | { "-flowsrc", 1, 0, unsetpflow_sender }, | |||
548 | { "flowdst", NEXTARG0xfffffe, 0, setpflow_receiver }, | |||
549 | { "-flowdst", 1, 0, unsetpflow_receiver }, | |||
550 | { "pflowproto", NEXTARG0xfffffe, 0, setpflowproto }, | |||
551 | { "-inet", AF_INET2, 0, removeaf }, | |||
552 | { "-inet6", AF_INET624, 0, removeaf }, | |||
553 | { "keepalive", NEXTARG20xfffffd, 0, NULL((void *)0), setkeepalive }, | |||
554 | { "-keepalive", 1, 0, unsetkeepalive }, | |||
555 | { "add", NEXTARG0xfffffe, 0, bridge_add }, | |||
556 | { "del", NEXTARG0xfffffe, 0, bridge_delete }, | |||
557 | { "addspan", NEXTARG0xfffffe, 0, bridge_addspan }, | |||
558 | { "delspan", NEXTARG0xfffffe, 0, bridge_delspan }, | |||
559 | { "discover", NEXTARG0xfffffe, 0, setdiscover }, | |||
560 | { "-discover", NEXTARG0xfffffe, 0, unsetdiscover }, | |||
561 | { "blocknonip", NEXTARG0xfffffe, 0, setblocknonip }, | |||
562 | { "-blocknonip",NEXTARG0xfffffe, 0, unsetblocknonip }, | |||
563 | { "learn", NEXTARG0xfffffe, 0, setlearn }, | |||
564 | { "-learn", NEXTARG0xfffffe, 0, unsetlearn }, | |||
565 | { "stp", NEXTARG0xfffffe, 0, setstp }, | |||
566 | { "-stp", NEXTARG0xfffffe, 0, unsetstp }, | |||
567 | { "edge", NEXTARG0xfffffe, 0, setedge }, | |||
568 | { "-edge", NEXTARG0xfffffe, 0, unsetedge }, | |||
569 | { "autoedge", NEXTARG0xfffffe, 0, setautoedge }, | |||
570 | { "-autoedge", NEXTARG0xfffffe, 0, unsetautoedge }, | |||
571 | { "protected", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_protect }, | |||
572 | { "-protected", NEXTARG0xfffffe, 0, bridge_unprotect }, | |||
573 | { "ptp", NEXTARG0xfffffe, 0, setptp }, | |||
574 | { "-ptp", NEXTARG0xfffffe, 0, unsetptp }, | |||
575 | { "autoptp", NEXTARG0xfffffe, 0, setautoptp }, | |||
576 | { "-autoptp", NEXTARG0xfffffe, 0, unsetautoptp }, | |||
577 | { "flush", 0, 0, bridge_flush }, | |||
578 | { "flushall", 0, 0, bridge_flushall }, | |||
579 | { "static", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_addaddr }, | |||
580 | { "endpoint", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_addendpoint }, | |||
581 | { "deladdr", NEXTARG0xfffffe, 0, bridge_deladdr }, | |||
582 | { "maxaddr", NEXTARG0xfffffe, 0, bridge_maxaddr }, | |||
583 | { "addr", 0, 0, bridge_addrs }, | |||
584 | { "hellotime", NEXTARG0xfffffe, 0, bridge_hellotime }, | |||
585 | { "fwddelay", NEXTARG0xfffffe, 0, bridge_fwddelay }, | |||
586 | { "maxage", NEXTARG0xfffffe, 0, bridge_maxage }, | |||
587 | { "proto", NEXTARG0xfffffe, 0, bridge_proto }, | |||
588 | { "ifpriority", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_ifprio }, | |||
589 | { "ifcost", NEXTARG20xfffffd, 0, NULL((void *)0), bridge_ifcost }, | |||
590 | { "-ifcost", NEXTARG0xfffffe, 0, bridge_noifcost }, | |||
591 | { "timeout", NEXTARG0xfffffe, 0, bridge_timeout }, | |||
592 | { "holdcnt", NEXTARG0xfffffe, 0, bridge_holdcnt }, | |||
593 | { "spanpriority", NEXTARG0xfffffe, 0, bridge_priority }, | |||
594 | { "ipdst", NEXTARG0xfffffe, 0, setifipdst }, | |||
595 | #if 0 | |||
596 | /* XXX `rule` special-cased below */ | |||
597 | { "rule", 0, 0, bridge_rule }, | |||
598 | #endif | |||
599 | { "rules", NEXTARG0xfffffe, 0, bridge_rules }, | |||
600 | { "rulefile", NEXTARG0xfffffe, 0, bridge_rulefile }, | |||
601 | { "flushrule", NEXTARG0xfffffe, 0, bridge_flushrule }, | |||
602 | { "description", NEXTARG0xfffffe, 0, setifdesc }, | |||
603 | { "descr", NEXTARG0xfffffe, 0, setifdesc }, | |||
604 | { "-description", 1, 0, unsetifdesc }, | |||
605 | { "-descr", 1, 0, unsetifdesc }, | |||
606 | { "wol", IFXF_WOL0x10, 0, setifxflags }, | |||
607 | { "-wol", -IFXF_WOL0x10, 0, setifxflags }, | |||
608 | { "pin", NEXTARG0xfffffe, 0, umb_setpin }, | |||
609 | { "chgpin", NEXTARG20xfffffd, 0, NULL((void *)0), umb_chgpin }, | |||
610 | { "puk", NEXTARG20xfffffd, 0, NULL((void *)0), umb_puk }, | |||
611 | { "apn", NEXTARG0xfffffe, 0, umb_apn }, | |||
612 | { "-apn", -1, 0, umb_apn }, | |||
613 | { "class", NEXTARG00xffffff, 0, umb_setclass }, | |||
614 | { "-class", -1, 0, umb_setclass }, | |||
615 | { "roaming", 1, 0, umb_roaming }, | |||
616 | { "-roaming", 0, 0, umb_roaming }, | |||
617 | { "patch", NEXTARG0xfffffe, 0, setpair }, | |||
618 | { "-patch", 1, 0, unsetpair }, | |||
619 | { "addlocal", NEXTARG0xfffffe, 0, addlocal }, | |||
620 | { "transceiver", NEXTARG00xffffff, 0, transceiver }, | |||
621 | { "sff", NEXTARG00xffffff, 0, transceiver }, | |||
622 | { "sffdump", 0, 0, transceiverdump }, | |||
623 | ||||
624 | { "wgpeer", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeer}, | |||
625 | { "wgdescription", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerdesc}, | |||
626 | { "wgdescr", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerdesc}, | |||
627 | { "wgendpoint", NEXTARG20xfffffd, A_WIREGUARD0x0040, NULL((void *)0), setwgpeerep}, | |||
628 | { "wgaip", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeeraip}, | |||
629 | { "wgpsk", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerpsk}, | |||
630 | { "wgpka", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgpeerpka}, | |||
631 | { "wgport", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgport}, | |||
632 | { "wgkey", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgkey}, | |||
633 | { "wgrtable", NEXTARG0xfffffe, A_WIREGUARD0x0040, setwgrtable}, | |||
634 | { "-wgpeer", NEXTARG0xfffffe, A_WIREGUARD0x0040, unsetwgpeer}, | |||
635 | { "-wgpsk", 0, A_WIREGUARD0x0040, unsetwgpeerpsk}, | |||
636 | { "-wgdescription", 0, A_WIREGUARD0x0040, unsetwgpeerdesc}, | |||
637 | { "-wgdescr", 0, A_WIREGUARD0x0040, unsetwgpeerdesc}, | |||
638 | { "-wgpeerall", 0, A_WIREGUARD0x0040, unsetwgpeerall}, | |||
639 | ||||
640 | #else /* SMALL */ | |||
641 | { "powersave", NEXTARG00xffffff, 0, setignore }, | |||
642 | { "priority", NEXTARG0xfffffe, 0, setignore }, | |||
643 | { "rtlabel", NEXTARG0xfffffe, 0, setignore }, | |||
644 | { "mpls", IFXF_MPLS0x8, 0, setignore }, | |||
645 | { "nwflag", NEXTARG0xfffffe, 0, setignore }, | |||
646 | { "rdomain", NEXTARG0xfffffe, 0, setignore }, | |||
647 | { "-inet", AF_INET2, 0, removeaf }, | |||
648 | { "-inet6", AF_INET624, 0, removeaf }, | |||
649 | { "description", NEXTARG0xfffffe, 0, setignore }, | |||
650 | { "descr", NEXTARG0xfffffe, 0, setignore }, | |||
651 | { "wol", IFXF_WOL0x10, 0, setignore }, | |||
652 | { "-wol", -IFXF_WOL0x10, 0, setignore }, | |||
653 | #endif /* SMALL */ | |||
654 | #if 0 | |||
655 | /* XXX `create' special-cased below */ | |||
656 | { "create", 0, 0, clone_create } , | |||
657 | #endif | |||
658 | { "destroy", 0, 0, clone_destroy } , | |||
659 | { "link0", IFF_LINK00x1000, 0, setifflags } , | |||
660 | { "-link0", -IFF_LINK00x1000, 0, setifflags } , | |||
661 | { "link1", IFF_LINK10x2000, 0, setifflags } , | |||
662 | { "-link1", -IFF_LINK10x2000, 0, setifflags } , | |||
663 | { "link2", IFF_LINK20x4000, 0, setifflags } , | |||
664 | { "-link2", -IFF_LINK20x4000, 0, setifflags } , | |||
665 | { "media", NEXTARG00xffffff, A_MEDIA0x0001, setmedia }, | |||
666 | { "mediaopt", NEXTARG0xfffffe, A_MEDIAOPTSET0x0002, setmediaopt }, | |||
667 | { "-mediaopt", NEXTARG0xfffffe, A_MEDIAOPTCLR0x0004, unsetmediaopt }, | |||
668 | { "mode", NEXTARG0xfffffe, A_MEDIAMODE0x0010, setmediamode }, | |||
669 | { "-mode", 0, A_MEDIAMODE0x0010, unsetmediamode }, | |||
670 | { "instance", NEXTARG0xfffffe, A_MEDIAINST0x0008, setmediainst }, | |||
671 | { "inst", NEXTARG0xfffffe, A_MEDIAINST0x0008, setmediainst }, | |||
672 | { "lladdr", NEXTARG0xfffffe, 0, setiflladdr }, | |||
673 | { "llprio", NEXTARG0xfffffe, 0, setifllprio }, | |||
674 | { NULL((void *)0), /*src*/ 0, 0, setifaddr }, | |||
675 | { NULL((void *)0), /*dst*/ 0, 0, setifdstaddr }, | |||
676 | { NULL((void *)0), /*illegal*/0, 0, NULL((void *)0) }, | |||
677 | }; | |||
678 | ||||
679 | #define IFFBITS"\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6STATICARP" "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" "\15LINK0\16LINK1\17LINK2\20MULTICAST" "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII" "\30AUTOCONF4" "\31MONITOR" "\32LRO" \ | |||
680 | "\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6STATICARP" \ | |||
681 | "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" \ | |||
682 | "\15LINK0\16LINK1\17LINK2\20MULTICAST" \ | |||
683 | "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII" \ | |||
684 | "\30AUTOCONF4" "\31MONITOR" "\32LRO" | |||
685 | ||||
686 | int getinfo(struct ifreq *, int); | |||
687 | void getsock(int); | |||
688 | void printgroupattribs(char *); | |||
689 | void printif(char *, int); | |||
690 | void printb_status(unsigned short, unsigned char *); | |||
691 | const char *get_linkstate(int, int); | |||
692 | void status(int, struct sockaddr_dl *, int, int); | |||
693 | __dead__attribute__((__noreturn__)) void usage(void); | |||
694 | const char *get_string(const char *, const char *, u_int8_t *, int *); | |||
695 | int len_string(const u_int8_t *, int); | |||
696 | int print_string(const u_int8_t *, int); | |||
697 | char *sec2str(time_t); | |||
698 | ||||
699 | const char *get_media_type_string(uint64_t); | |||
700 | const char *get_media_subtype_string(uint64_t); | |||
701 | uint64_t get_media_mode(uint64_t, const char *); | |||
702 | uint64_t get_media_subtype(uint64_t, const char *); | |||
703 | uint64_t get_media_options(uint64_t, const char *); | |||
704 | uint64_t lookup_media_word(const struct ifmedia_description *, uint64_t, | |||
705 | const char *); | |||
706 | void print_media_word(uint64_t, int, int); | |||
707 | void process_media_commands(void); | |||
708 | void init_current_media(void); | |||
709 | ||||
710 | void process_join_commands(void); | |||
711 | ||||
712 | void process_wg_commands(void); | |||
713 | ||||
714 | unsigned long get_ts_map(int, int, int); | |||
715 | ||||
716 | void in_status(int); | |||
717 | void in_getaddr(const char *, int); | |||
718 | void in_getprefix(const char *, int); | |||
719 | void in6_fillscopeid(struct sockaddr_in6 *); | |||
720 | void in6_alias(struct in6_ifreq *); | |||
721 | void in6_status(int); | |||
722 | void in6_getaddr(const char *, int); | |||
723 | void in6_getprefix(const char *, int); | |||
724 | void ieee80211_status(void); | |||
725 | void join_status(void); | |||
726 | void ieee80211_listchans(void); | |||
727 | void ieee80211_listnodes(void); | |||
728 | void ieee80211_printnode(struct ieee80211_nodereq *); | |||
729 | u_int getwpacipher(const char *); | |||
730 | void print_cipherset(u_int32_t); | |||
731 | ||||
732 | void spppauthinfo(struct sauthreq *, int); | |||
733 | void spppdnsinfo(struct sdnsreq *); | |||
734 | ||||
735 | /* Known address families */ | |||
736 | const struct afswtch { | |||
737 | char *af_name; | |||
738 | short af_af; | |||
739 | void (*af_status)(int); | |||
740 | void (*af_getaddr)(const char *, int); | |||
741 | void (*af_getprefix)(const char *, int); | |||
742 | u_long af_difaddr; | |||
743 | u_long af_aifaddr; | |||
744 | caddr_t af_ridreq; | |||
745 | caddr_t af_addreq; | |||
746 | } afs[] = { | |||
747 | #define C(x)((caddr_t) &x) ((caddr_t) &x) | |||
748 | { "inet", AF_INET2, in_status, in_getaddr, in_getprefix, | |||
749 | SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((25))), SIOCAIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifaliasreq) & 0x1fff) << 16) | ((('i')) << 8) | ((26))), C(ridreq)((caddr_t) &ridreq), C(in_addreq)((caddr_t) &in_addreq) }, | |||
750 | { "inet6", AF_INET624, in6_status, in6_getaddr, in6_getprefix, | |||
751 | SIOCDIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((25))), SIOCAIFADDR_IN6((unsigned long)0x80000000 | ((sizeof(struct in6_aliasreq) & 0x1fff) << 16) | ((('i')) << 8) | ((26))), C(in6_ridreq)((caddr_t) &in6_ridreq), C(in6_addreq)((caddr_t) &in6_addreq) }, | |||
752 | { 0, 0, 0, 0 } | |||
753 | }; | |||
754 | ||||
755 | const struct afswtch *afp; /*the address family being set or asked about*/ | |||
756 | ||||
757 | char joinname[IEEE80211_NWID_LEN32]; | |||
758 | size_t joinlen; | |||
759 | char nwidname[IEEE80211_NWID_LEN32]; | |||
760 | size_t nwidlen; | |||
761 | ||||
762 | int ifaliases = 0; | |||
763 | int aflag = 0; | |||
764 | ||||
765 | int | |||
766 | main(int argc, char *argv[]) | |||
767 | { | |||
768 | const struct afswtch *rafp = NULL((void *)0); | |||
769 | int create = 0; | |||
770 | int Cflag = 0; | |||
771 | int gflag = 0; | |||
772 | int found_rulefile = 0; | |||
773 | int i; | |||
774 | ||||
775 | /* If no args at all, print all interfaces. */ | |||
776 | if (argc < 2) { | |||
| ||||
777 | /* no filesystem visibility */ | |||
778 | if (unveil("/", "") == -1) | |||
779 | err(1, "unveil /"); | |||
780 | if (unveil(NULL((void *)0), NULL((void *)0)) == -1) | |||
781 | err(1, "unveil"); | |||
782 | aflag = 1; | |||
783 | printif(NULL((void *)0), 0); | |||
784 | return (0); | |||
785 | } | |||
786 | argc--, argv++; | |||
787 | if (*argv[0] == '-') { | |||
788 | int nomore = 0; | |||
789 | ||||
790 | for (i = 1; argv[0][i]; i++) { | |||
791 | switch (argv[0][i]) { | |||
792 | case 'a': | |||
793 | aflag = 1; | |||
794 | nomore = 1; | |||
795 | break; | |||
796 | case 'A': | |||
797 | aflag = 1; | |||
798 | ifaliases = 1; | |||
799 | nomore = 1; | |||
800 | break; | |||
801 | case 'g': | |||
802 | gflag = 1; | |||
803 | break; | |||
804 | case 'C': | |||
805 | Cflag = 1; | |||
806 | nomore = 1; | |||
807 | break; | |||
808 | case 'M': | |||
809 | if (argv[1] == NULL((void *)0)) | |||
810 | usage(); | |||
811 | exit(findmac(argv[1])); | |||
812 | break; | |||
813 | default: | |||
814 | usage(); | |||
815 | break; | |||
816 | } | |||
817 | } | |||
818 | if (nomore == 0) { | |||
819 | argc--, argv++; | |||
820 | if (argc < 1) | |||
821 | usage(); | |||
822 | if (strlcpy(ifname, *argv, sizeof(ifname)) >= IFNAMSIZ16) | |||
823 | errx(1, "interface name '%s' too long", *argv); | |||
824 | } | |||
825 | } else if (strlcpy(ifname, *argv, sizeof(ifname)) >= IFNAMSIZ16) | |||
826 | errx(1, "interface name '%s' too long", *argv); | |||
827 | argc--, argv++; | |||
828 | ||||
829 | for (i = 0; i < argc; i++) { | |||
830 | if (strcmp(argv[i], "rulefile") == 0) { | |||
831 | found_rulefile = 1; | |||
832 | break; | |||
833 | } | |||
834 | } | |||
835 | ||||
836 | if (!found_rulefile) { | |||
837 | if (unveil(_PATH_RESCONF"/etc/resolv.conf", "r") == -1) | |||
838 | err(1, "unveil %s", _PATH_RESCONF"/etc/resolv.conf"); | |||
839 | if (unveil(_PATH_HOSTS"/etc/hosts", "r") == -1) | |||
840 | err(1, "unveil %s", _PATH_HOSTS"/etc/hosts"); | |||
841 | if (unveil(_PATH_SERVICES"/etc/services", "r") == -1) | |||
842 | err(1, "unveil %s", _PATH_SERVICES"/etc/services"); | |||
843 | if (unveil(NULL((void *)0), NULL((void *)0)) == -1) | |||
844 | err(1, "unveil"); | |||
845 | } | |||
846 | ||||
847 | if (argc > 0) { | |||
848 | for (afp = rafp = afs; rafp->af_name; rafp++) | |||
849 | if (strcmp(rafp->af_name, *argv) == 0) { | |||
850 | afp = rafp; | |||
851 | argc--; | |||
852 | argv++; | |||
853 | break; | |||
854 | } | |||
855 | rafp = afp; | |||
856 | af = ifr.ifr_addrifr_ifru.ifru_addr.sa_family = rafp->af_af; | |||
857 | } | |||
858 | if (Cflag) { | |||
859 | if (argc > 0 || aflag) | |||
860 | usage(); | |||
861 | list_cloners(); | |||
862 | return (0); | |||
863 | } | |||
864 | if (gflag) { | |||
865 | if (argc == 0) | |||
866 | printgroupattribs(ifname); | |||
867 | else | |||
868 | setgroupattribs(ifname, argc, argv); | |||
869 | return (0); | |||
870 | } | |||
871 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
872 | ||||
873 | /* initialization */ | |||
874 | in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME0xffffffff; | |||
875 | in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME0xffffffff; | |||
876 | ||||
877 | /* | |||
878 | * NOTE: We must special-case the `create' command right | |||
879 | * here as we would otherwise fail in getinfo(). | |||
880 | */ | |||
881 | if (argc > 0 && strcmp(argv[0], "create") == 0) { | |||
882 | clone_create(argv[0], 0); | |||
883 | argc--, argv++; | |||
884 | if (argc == 0) | |||
885 | return (0); | |||
886 | } | |||
887 | if (aflag == 0) { | |||
888 | create = (argc > 0) && strcmp(argv[0], "destroy") != 0; | |||
889 | (void)getinfo(&ifr, create); | |||
890 | } | |||
891 | ||||
892 | if (argc != 0 && af == AF_INET624) | |||
893 | addaf(ifname, AF_INET624); | |||
894 | ||||
895 | while (argc > 0) { | |||
896 | const struct cmd *p; | |||
897 | ||||
898 | for (p = cmds; p->c_name; p++) | |||
899 | if (strcmp(*argv, p->c_name) == 0) | |||
900 | break; | |||
901 | #ifndef SMALL | |||
902 | if (strcmp(*argv, "rule") == 0) { | |||
903 | argc--, argv++; | |||
904 | return bridge_rule(argc, argv, -1); | |||
905 | } | |||
906 | #endif | |||
907 | if (p->c_name == 0 && setaddr) | |||
908 | for (i = setaddr; i > 0; i--) { | |||
909 | p++; | |||
910 | if (p->c_func == NULL((void *)0)) | |||
911 | errx(1, "%s: bad value", *argv); | |||
912 | } | |||
913 | if (p->c_func || p->c_func2) { | |||
914 | if (p->c_parameter == NEXTARG00xffffff) { | |||
915 | const struct cmd *p0; | |||
916 | int noarg = 1; | |||
917 | ||||
918 | if (argv[1]) { | |||
919 | for (p0 = cmds; p0->c_name; p0++) | |||
920 | if (strcmp(argv[1], | |||
921 | p0->c_name) == 0) { | |||
922 | noarg = 0; | |||
923 | break; | |||
924 | } | |||
925 | } else | |||
926 | noarg = 0; | |||
927 | ||||
928 | if (noarg == 0) | |||
929 | (*p->c_func)(NULL((void *)0), 0); | |||
930 | else | |||
931 | goto nextarg; | |||
932 | } else if (p->c_parameter == NEXTARG0xfffffe) { | |||
933 | nextarg: | |||
934 | if (argv[1] == NULL((void *)0)) | |||
935 | errx(1, "'%s' requires argument", | |||
936 | p->c_name); | |||
937 | (*p->c_func)(argv[1], 0); | |||
938 | argc--, argv++; | |||
939 | actions = actions | A_SILENT0x8000000 | p->c_action; | |||
940 | } else if (p->c_parameter == NEXTARG20xfffffd) { | |||
941 | if ((argv[1] == NULL((void *)0)) || | |||
942 | (argv[2] == NULL((void *)0))) | |||
943 | errx(1, "'%s' requires 2 arguments", | |||
944 | p->c_name); | |||
945 | (*p->c_func2)(argv[1], argv[2]); | |||
946 | argc -= 2; | |||
947 | argv += 2; | |||
948 | actions = actions | A_SILENT0x8000000 | p->c_action; | |||
949 | } else { | |||
950 | (*p->c_func)(*argv, p->c_parameter); | |||
951 | actions = actions | A_SILENT0x8000000 | p->c_action; | |||
952 | } | |||
953 | } | |||
954 | argc--, argv++; | |||
955 | } | |||
956 | ||||
957 | if (argc == 0 && actions == 0) { | |||
958 | printif(ifr.ifr_name, aflag ? ifaliases : 1); | |||
959 | return (0); | |||
960 | } | |||
961 | ||||
962 | #ifndef SMALL | |||
963 | process_wg_commands(); | |||
964 | #endif | |||
965 | ||||
966 | process_join_commands(); | |||
967 | ||||
968 | /* Process any media commands that may have been issued. */ | |||
969 | process_media_commands(); | |||
970 | ||||
971 | if (af == AF_INET624 && explicit_prefix == 0) { | |||
972 | /* | |||
973 | * Aggregatable address architecture defines all prefixes | |||
974 | * are 64. So, it is convenient to set prefixlen to 64 if | |||
975 | * it is not specified. If we are setting a destination | |||
976 | * address on a point-to-point interface, 128 is required. | |||
977 | */ | |||
978 | if (setipdst && (flags & IFF_POINTOPOINT0x10)) | |||
979 | setifprefixlen("128", 0); | |||
980 | else | |||
981 | setifprefixlen("64", 0); | |||
982 | /* in6_getprefix("64", MASK) if MASK is available here... */ | |||
983 | } | |||
984 | ||||
985 | if (clearaddr) { | |||
986 | (void) strlcpy(rafp->af_ridreq, ifname, sizeof(ifr.ifr_name)); | |||
987 | if (ioctl(sock, rafp->af_difaddr, rafp->af_ridreq) == -1) { | |||
988 | if (errno(*__errno()) == EADDRNOTAVAIL49 && (doalias >= 0)) { | |||
989 | /* means no previous address for interface */ | |||
990 | } else | |||
991 | err(1, "SIOCDIFADDR"); | |||
992 | } | |||
993 | } | |||
994 | if (newaddr) { | |||
995 | (void) strlcpy(rafp->af_addreq, ifname, sizeof(ifr.ifr_name)); | |||
996 | if (ioctl(sock, rafp->af_aifaddr, rafp->af_addreq) == -1) | |||
997 | err(1, "SIOCAIFADDR"); | |||
998 | } | |||
999 | return (0); | |||
1000 | } | |||
1001 | ||||
1002 | void | |||
1003 | getsock(int naf) | |||
1004 | { | |||
1005 | static int oaf = -1; | |||
1006 | ||||
1007 | if (oaf == naf) | |||
1008 | return; | |||
1009 | if (oaf != -1) | |||
1010 | close(sock); | |||
1011 | sock = socket(naf, SOCK_DGRAM2, 0); | |||
1012 | if (sock == -1) | |||
1013 | oaf = -1; | |||
1014 | else | |||
1015 | oaf = naf; | |||
1016 | } | |||
1017 | ||||
1018 | int | |||
1019 | getinfo(struct ifreq *ifr, int create) | |||
1020 | { | |||
1021 | ||||
1022 | getsock(af); | |||
1023 | if (sock == -1) | |||
1024 | err(1, "socket"); | |||
1025 | if (!isdigit((unsigned char)ifname[strlen(ifname) - 1])) | |||
1026 | return (-1); /* ignore groups here */ | |||
1027 | if (ioctl(sock, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((17))), (caddr_t)ifr) == -1) { | |||
1028 | int oerrno = errno(*__errno()); | |||
1029 | ||||
1030 | if (!create) | |||
1031 | return (-1); | |||
1032 | if (ioctl(sock, SIOCIFCREATE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((122))), (caddr_t)ifr) == -1) { | |||
1033 | errno(*__errno()) = oerrno; | |||
1034 | return (-1); | |||
1035 | } | |||
1036 | if (ioctl(sock, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((17))), (caddr_t)ifr) == -1) | |||
1037 | return (-1); | |||
1038 | } | |||
1039 | flags = ifr->ifr_flagsifr_ifru.ifru_flags & 0xffff; | |||
1040 | if (ioctl(sock, SIOCGIFXFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((158))), (caddr_t)ifr) == -1) | |||
1041 | ifr->ifr_flagsifr_ifru.ifru_flags = 0; | |||
1042 | xflags = ifr->ifr_flagsifr_ifru.ifru_flags; | |||
1043 | if (ioctl(sock, SIOCGIFMETRIC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((23))), (caddr_t)ifr) == -1) | |||
1044 | metric = 0; | |||
1045 | else | |||
1046 | metric = ifr->ifr_metricifr_ifru.ifru_metric; | |||
1047 | if (ioctl(sock, SIOCGIFMTU(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((126))), (caddr_t)ifr) == -1) | |||
1048 | mtu = 0; | |||
1049 | else | |||
1050 | mtu = ifr->ifr_mtuifr_ifru.ifru_metric; | |||
1051 | #ifndef SMALL | |||
1052 | if (ioctl(sock, SIOCGIFRDOMAIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((160))), (caddr_t)ifr) == -1) | |||
1053 | rdomainid = 0; | |||
1054 | else | |||
1055 | rdomainid = ifr->ifr_rdomainidifr_ifru.ifru_metric; | |||
1056 | #endif | |||
1057 | if (ioctl(sock, SIOCGIFLLPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((182))), (caddr_t)ifr) == -1) | |||
1058 | llprio = 0; | |||
1059 | else | |||
1060 | llprio = ifr->ifr_llprioifr_ifru.ifru_metric; | |||
1061 | ||||
1062 | return (0); | |||
1063 | } | |||
1064 | ||||
1065 | int | |||
1066 | printgroup(char *groupname, int ifaliases) | |||
1067 | { | |||
1068 | struct ifgroupreq ifgr; | |||
1069 | struct ifg_req *ifg; | |||
1070 | int len, cnt = 0; | |||
1071 | ||||
1072 | getsock(AF_INET2); | |||
1073 | bzero(&ifgr, sizeof(ifgr)); | |||
1074 | strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); | |||
1075 | if (ioctl(sock, SIOCGIFGMEMB(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((138))), (caddr_t)&ifgr) == -1) { | |||
1076 | if (errno(*__errno()) == EINVAL22 || errno(*__errno()) == ENOTTY25 || | |||
1077 | errno(*__errno()) == ENOENT2) | |||
1078 | return (-1); | |||
1079 | else | |||
1080 | err(1, "%s: SIOCGIFGMEMB", ifgr.ifgr_name); | |||
1081 | } | |||
1082 | ||||
1083 | len = ifgr.ifgr_len; | |||
1084 | if ((ifgr.ifgr_groupsifgr_ifgru.ifgru_groups = calloc(1, len)) == NULL((void *)0)) | |||
1085 | err(1, "printgroup"); | |||
1086 | if (ioctl(sock, SIOCGIFGMEMB(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((138))), (caddr_t)&ifgr) == -1) | |||
1087 | err(1, "%s: SIOCGIFGMEMB", ifgr.ifgr_name); | |||
1088 | ||||
1089 | for (ifg = ifgr.ifgr_groupsifgr_ifgru.ifgru_groups; ifg && len >= sizeof(struct ifg_req); | |||
1090 | ifg++) { | |||
1091 | len -= sizeof(struct ifg_req); | |||
1092 | printif(ifg->ifgrq_memberifgrq_ifgrqu.ifgrqu_member, ifaliases); | |||
1093 | cnt++; | |||
1094 | } | |||
1095 | free(ifgr.ifgr_groupsifgr_ifgru.ifgru_groups); | |||
1096 | ||||
1097 | return (cnt); | |||
1098 | } | |||
1099 | ||||
1100 | void | |||
1101 | printgroupattribs(char *groupname) | |||
1102 | { | |||
1103 | struct ifgroupreq ifgr; | |||
1104 | ||||
1105 | getsock(AF_INET2); | |||
1106 | bzero(&ifgr, sizeof(ifgr)); | |||
1107 | strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); | |||
1108 | if (ioctl(sock, SIOCGIFGATTR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((139))), (caddr_t)&ifgr) == -1) | |||
1109 | err(1, "%s: SIOCGIFGATTR", ifgr.ifgr_name); | |||
1110 | ||||
1111 | printf("%s:", groupname); | |||
1112 | printf(" carp demote count %d", ifgr.ifgr_attribifgr_ifgru.ifgru_attrib.ifg_carp_demoted); | |||
1113 | printf("\n"); | |||
1114 | } | |||
1115 | ||||
1116 | void | |||
1117 | setgroupattribs(char *groupname, int argc, char *argv[]) | |||
1118 | { | |||
1119 | const char *errstr; | |||
1120 | char *p = argv[0]; | |||
1121 | int neg = 1; | |||
1122 | ||||
1123 | struct ifgroupreq ifgr; | |||
1124 | ||||
1125 | getsock(AF_INET2); | |||
1126 | bzero(&ifgr, sizeof(ifgr)); | |||
1127 | strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); | |||
1128 | ||||
1129 | if (argc > 1) { | |||
1130 | neg = strtonum(argv[1], 0, 128, &errstr); | |||
1131 | if (errstr) | |||
1132 | errx(1, "%s: invalid carp demotion: %s", ifgr.ifgr_name, | |||
1133 | errstr); | |||
1134 | } | |||
1135 | ||||
1136 | if (p[0] == '-') { | |||
1137 | neg = neg * -1; | |||
1138 | p++; | |||
1139 | } | |||
1140 | if (!strcmp(p, "carpdemote")) | |||
1141 | ifgr.ifgr_attribifgr_ifgru.ifgru_attrib.ifg_carp_demoted = neg; | |||
1142 | else | |||
1143 | usage(); | |||
1144 | ||||
1145 | if (ioctl(sock, SIOCSIFGATTR((unsigned long)0x80000000 | ((sizeof(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((140))), (caddr_t)&ifgr) == -1) | |||
1146 | err(1, "%s: SIOCSIFGATTR", ifgr.ifgr_name); | |||
1147 | } | |||
1148 | ||||
1149 | void | |||
1150 | printif(char *name, int ifaliases) | |||
1151 | { | |||
1152 | struct ifaddrs *ifap, *ifa; | |||
1153 | struct if_data *ifdata; | |||
1154 | const char *namep; | |||
1155 | char *oname = NULL((void *)0); | |||
1156 | struct ifreq *ifrp; | |||
1157 | int count = 0, noinet = 1; | |||
1158 | size_t nlen = 0; | |||
1159 | ||||
1160 | if (aflag
| |||
1161 | name = NULL((void *)0); | |||
1162 | if (name
| |||
1163 | if ((oname = strdup(name)) == NULL((void *)0)) | |||
1164 | err(1, "strdup"); | |||
1165 | nlen = strlen(oname); | |||
1166 | /* is it a group? */ | |||
1167 | if (nlen && !isdigit((unsigned char)oname[nlen - 1])) | |||
1168 | if (printgroup(oname, ifaliases) != -1) { | |||
1169 | free(oname); | |||
1170 | return; | |||
1171 | } | |||
1172 | } | |||
1173 | ||||
1174 | if (getifaddrs(&ifap) != 0) | |||
1175 | err(1, "getifaddrs"); | |||
1176 | ||||
1177 | namep = NULL((void *)0); | |||
1178 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | |||
1179 | if (oname
| |||
1180 | if (nlen && isdigit((unsigned char)oname[nlen - 1])) { | |||
1181 | /* must have exact match */ | |||
1182 | if (strcmp(oname, ifa->ifa_name) != 0) | |||
1183 | continue; | |||
1184 | } else { | |||
1185 | /* partial match OK if it ends w/ digit */ | |||
1186 | if (strncmp(oname, ifa->ifa_name, nlen) != 0 || | |||
1187 | !isdigit((unsigned char)ifa->ifa_name[nlen])) | |||
1188 | continue; | |||
1189 | } | |||
1190 | } | |||
1191 | /* quickhack: sizeof(ifr) < sizeof(ifr6) */ | |||
1192 | if (ifa->ifa_addr != NULL((void *)0) && | |||
1193 | ifa->ifa_addr->sa_family == AF_INET624) { | |||
1194 | memset(&ifr6, 0, sizeof(ifr6)); | |||
1195 | memcpy(&ifr6.ifr_addrifr_ifru.ifru_addr, ifa->ifa_addr, | |||
1196 | MINIMUM(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len)(((sizeof(ifr6.ifr_ifru.ifru_addr)) < (ifa->ifa_addr-> sa_len)) ? (sizeof(ifr6.ifr_ifru.ifru_addr)) : (ifa->ifa_addr ->sa_len))); | |||
1197 | ifrp = (struct ifreq *)&ifr6; | |||
1198 | } else if (ifa->ifa_addr
| |||
1199 | memset(&ifr, 0, sizeof(ifr)); | |||
1200 | memcpy(&ifr.ifr_addrifr_ifru.ifru_addr, ifa->ifa_addr, | |||
1201 | MINIMUM(sizeof(ifr.ifr_addr), ifa->ifa_addr->sa_len)(((sizeof(ifr.ifr_ifru.ifru_addr)) < (ifa->ifa_addr-> sa_len)) ? (sizeof(ifr.ifr_ifru.ifru_addr)) : (ifa->ifa_addr ->sa_len))); | |||
1202 | ifrp = 𝔦 | |||
1203 | } | |||
1204 | strlcpy(ifname, ifa->ifa_name, sizeof(ifname)); | |||
1205 | strlcpy(ifrp->ifr_name, ifa->ifa_name, sizeof(ifrp->ifr_name)); | |||
| ||||
1206 | ||||
1207 | if (ifa->ifa_addr != NULL((void *)0) && | |||
1208 | ifa->ifa_addr->sa_family == AF_LINK18) { | |||
1209 | namep = ifa->ifa_name; | |||
1210 | if (getinfo(ifrp, 0) < 0) | |||
1211 | continue; | |||
1212 | ifdata = ifa->ifa_data; | |||
1213 | status(1, (struct sockaddr_dl *)ifa->ifa_addr, | |||
1214 | ifdata->ifi_link_state, ifaliases); | |||
1215 | count++; | |||
1216 | noinet = 1; | |||
1217 | continue; | |||
1218 | } | |||
1219 | ||||
1220 | if (!namep || !strcmp(namep, ifa->ifa_name)) { | |||
1221 | const struct afswtch *p; | |||
1222 | ||||
1223 | if (ifa->ifa_addr == NULL((void *)0) || | |||
1224 | (ifa->ifa_addr->sa_family == AF_INET2 && | |||
1225 | ifaliases == 0 && noinet == 0)) | |||
1226 | continue; | |||
1227 | if ((p = afp) != NULL((void *)0)) { | |||
1228 | if (ifa->ifa_addr->sa_family == p->af_af) | |||
1229 | p->af_status(1); | |||
1230 | } else { | |||
1231 | for (p = afs; p->af_name; p++) { | |||
1232 | if (ifa->ifa_addr->sa_family == | |||
1233 | p->af_af) | |||
1234 | p->af_status(0); | |||
1235 | } | |||
1236 | } | |||
1237 | count++; | |||
1238 | if (ifa->ifa_addr->sa_family == AF_INET2) | |||
1239 | noinet = 0; | |||
1240 | continue; | |||
1241 | } | |||
1242 | } | |||
1243 | freeifaddrs(ifap); | |||
1244 | free(oname); | |||
1245 | if (count == 0) { | |||
1246 | fprintf(stderr(&__sF[2]), "%s: no such interface\n", ifname); | |||
1247 | exit(1); | |||
1248 | } | |||
1249 | } | |||
1250 | ||||
1251 | void | |||
1252 | clone_create(const char *addr, int param) | |||
1253 | { | |||
1254 | ||||
1255 | /* We're called early... */ | |||
1256 | getsock(AF_INET2); | |||
1257 | ||||
1258 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1259 | if (ioctl(sock, SIOCIFCREATE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((122))), &ifr) == -1) | |||
1260 | err(1, "%s: SIOCIFCREATE", ifr.ifr_name); | |||
1261 | } | |||
1262 | ||||
1263 | void | |||
1264 | clone_destroy(const char *addr, int param) | |||
1265 | { | |||
1266 | ||||
1267 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1268 | if (ioctl(sock, SIOCIFDESTROY((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((121))), &ifr) == -1) | |||
1269 | err(1, "%s: SIOCIFDESTROY", ifr.ifr_name); | |||
1270 | } | |||
1271 | ||||
1272 | struct if_clonereq * | |||
1273 | get_cloners(void) | |||
1274 | { | |||
1275 | static struct if_clonereq ifcr; | |||
1276 | ||||
1277 | memset(&ifcr, 0, sizeof(ifcr)); | |||
1278 | ||||
1279 | getsock(AF_INET2); | |||
1280 | ||||
1281 | if (ioctl(sock, SIOCIFGCLONERS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct if_clonereq) & 0x1fff) << 16) | ((('i')) << 8) | ((120))), &ifcr) == -1) | |||
1282 | err(1, "SIOCIFGCLONERS for count"); | |||
1283 | ||||
1284 | if ((ifcr.ifcr_buffer = calloc(ifcr.ifcr_total, IFNAMSIZ16)) == NULL((void *)0)) | |||
1285 | err(1, "unable to allocate cloner name buffer"); | |||
1286 | ifcr.ifcr_count = ifcr.ifcr_total; | |||
1287 | ||||
1288 | if (ioctl(sock, SIOCIFGCLONERS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct if_clonereq) & 0x1fff) << 16) | ((('i')) << 8) | ((120))), &ifcr) == -1) | |||
1289 | err(1, "SIOCIFGCLONERS for names"); | |||
1290 | ||||
1291 | /* | |||
1292 | * In case some disappeared in the mean time, clamp it down. | |||
1293 | */ | |||
1294 | if (ifcr.ifcr_count > ifcr.ifcr_total) | |||
1295 | ifcr.ifcr_count = ifcr.ifcr_total; | |||
1296 | ||||
1297 | return &ifcr; | |||
1298 | } | |||
1299 | ||||
1300 | void | |||
1301 | list_cloners(void) | |||
1302 | { | |||
1303 | struct if_clonereq *ifcr; | |||
1304 | char *cp, *buf; | |||
1305 | int idx; | |||
1306 | ||||
1307 | ifcr = get_cloners(); | |||
1308 | buf = ifcr->ifcr_buffer; | |||
1309 | ||||
1310 | qsort(buf, ifcr->ifcr_count, IFNAMSIZ16, | |||
1311 | (int(*)(const void *, const void *))strcmp); | |||
1312 | ||||
1313 | for (cp = buf, idx = 0; idx < ifcr->ifcr_count; idx++, cp += IFNAMSIZ16) { | |||
1314 | if (idx > 0) | |||
1315 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
1316 | printf("%s", cp); | |||
1317 | } | |||
1318 | ||||
1319 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
1320 | free(ifcr->ifcr_buffer); | |||
1321 | } | |||
1322 | ||||
1323 | #define RIDADDR0 0 | |||
1324 | #define ADDR1 1 | |||
1325 | #define MASK2 2 | |||
1326 | #define DSTADDR3 3 | |||
1327 | ||||
1328 | void | |||
1329 | setifaddr(const char *addr, int param) | |||
1330 | { | |||
1331 | /* | |||
1332 | * Delay the ioctl to set the interface addr until flags are all set. | |||
1333 | * The address interpretation may depend on the flags, | |||
1334 | * and the flags may change when the address is set. | |||
1335 | */ | |||
1336 | setaddr++; | |||
1337 | if (doalias >= 0) | |||
1338 | newaddr = 1; | |||
1339 | if (doalias == 0) | |||
1340 | clearaddr = 1; | |||
1341 | afp->af_getaddr(addr, (doalias >= 0 ? ADDR1 : RIDADDR0)); | |||
1342 | } | |||
1343 | ||||
1344 | #ifndef SMALL | |||
1345 | void | |||
1346 | setifrtlabel(const char *label, int d) | |||
1347 | { | |||
1348 | if (d != 0) | |||
1349 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)(const char *)""; | |||
1350 | else | |||
1351 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)label; | |||
1352 | if (ioctl(sock, SIOCSIFRTLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((130))), &ifr) == -1) | |||
1353 | warn("SIOCSIFRTLABEL"); | |||
1354 | } | |||
1355 | #endif | |||
1356 | ||||
1357 | void | |||
1358 | setifnetmask(const char *addr, int ignored) | |||
1359 | { | |||
1360 | afp->af_getaddr(addr, MASK2); | |||
1361 | explicit_prefix = 1; | |||
1362 | } | |||
1363 | ||||
1364 | void | |||
1365 | setifbroadaddr(const char *addr, int ignored) | |||
1366 | { | |||
1367 | afp->af_getaddr(addr, DSTADDR3); | |||
1368 | } | |||
1369 | ||||
1370 | #ifndef SMALL | |||
1371 | void | |||
1372 | setifdesc(const char *val, int ignored) | |||
1373 | { | |||
1374 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)val; | |||
1375 | if (ioctl(sock, SIOCSIFDESCR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((128))), &ifr) == -1) | |||
1376 | warn("SIOCSIFDESCR"); | |||
1377 | } | |||
1378 | ||||
1379 | void | |||
1380 | unsetifdesc(const char *noval, int ignored) | |||
1381 | { | |||
1382 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)(const char *)""; | |||
1383 | if (ioctl(sock, SIOCSIFDESCR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((128))), &ifr) == -1) | |||
1384 | warn("SIOCSIFDESCR"); | |||
1385 | } | |||
1386 | ||||
1387 | void | |||
1388 | setifipdst(const char *addr, int ignored) | |||
1389 | { | |||
1390 | in_getaddr(addr, DSTADDR3); | |||
1391 | setipdst++; | |||
1392 | clearaddr = 0; | |||
1393 | newaddr = 0; | |||
1394 | } | |||
1395 | #endif | |||
1396 | ||||
1397 | #define rqtosa(x)(&(((struct ifreq *)(afp->x))->ifr_ifru.ifru_addr)) (&(((struct ifreq *)(afp->x))->ifr_addrifr_ifru.ifru_addr)) | |||
1398 | void | |||
1399 | notealias(const char *addr, int param) | |||
1400 | { | |||
1401 | if (setaddr && doalias == 0 && param < 0) | |||
1402 | memcpy(rqtosa(af_ridreq)(&(((struct ifreq *)(afp->af_ridreq))->ifr_ifru.ifru_addr )), rqtosa(af_addreq)(&(((struct ifreq *)(afp->af_addreq))->ifr_ifru.ifru_addr )), | |||
1403 | rqtosa(af_addreq)(&(((struct ifreq *)(afp->af_addreq))->ifr_ifru.ifru_addr ))->sa_len); | |||
1404 | doalias = param; | |||
1405 | if (param < 0) { | |||
1406 | clearaddr = 1; | |||
1407 | newaddr = 0; | |||
1408 | } else | |||
1409 | clearaddr = 0; | |||
1410 | } | |||
1411 | ||||
1412 | void | |||
1413 | setifdstaddr(const char *addr, int param) | |||
1414 | { | |||
1415 | setaddr++; | |||
1416 | setipdst++; | |||
1417 | afp->af_getaddr(addr, DSTADDR3); | |||
1418 | } | |||
1419 | ||||
1420 | /* | |||
1421 | * Note: doing an SIOCGIFFLAGS scribbles on the union portion | |||
1422 | * of the ifreq structure, which may confuse other parts of ifconfig. | |||
1423 | * Make a private copy so we can avoid that. | |||
1424 | */ | |||
1425 | void | |||
1426 | setifflags(const char *vname, int value) | |||
1427 | { | |||
1428 | struct ifreq my_ifr; | |||
1429 | ||||
1430 | bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); | |||
1431 | ||||
1432 | if (ioctl(sock, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((17))), (caddr_t)&my_ifr) == -1) | |||
1433 | err(1, "%s: SIOCGIFFLAGS", my_ifr.ifr_name); | |||
1434 | (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name)); | |||
1435 | flags = my_ifr.ifr_flagsifr_ifru.ifru_flags; | |||
1436 | ||||
1437 | if (value < 0) { | |||
1438 | value = -value; | |||
1439 | flags &= ~value; | |||
1440 | } else | |||
1441 | flags |= value; | |||
1442 | my_ifr.ifr_flagsifr_ifru.ifru_flags = flags; | |||
1443 | if (ioctl(sock, SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((16))), (caddr_t)&my_ifr) == -1) | |||
1444 | err(1, "%s: SIOCSIFFLAGS", my_ifr.ifr_name); | |||
1445 | } | |||
1446 | ||||
1447 | void | |||
1448 | setifxflags(const char *vname, int value) | |||
1449 | { | |||
1450 | struct ifreq my_ifr; | |||
1451 | ||||
1452 | bcopy((char *)&ifr, (char *)&my_ifr, sizeof(struct ifreq)); | |||
1453 | ||||
1454 | if (ioctl(sock, SIOCGIFXFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((158))), (caddr_t)&my_ifr) == -1) | |||
1455 | warn("%s: SIOCGIFXFLAGS", my_ifr.ifr_name); | |||
1456 | (void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name)); | |||
1457 | xflags = my_ifr.ifr_flagsifr_ifru.ifru_flags; | |||
1458 | ||||
1459 | if (value < 0) { | |||
1460 | value = -value; | |||
1461 | xflags &= ~value; | |||
1462 | } else | |||
1463 | xflags |= value; | |||
1464 | my_ifr.ifr_flagsifr_ifru.ifru_flags = xflags; | |||
1465 | if (ioctl(sock, SIOCSIFXFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((157))), (caddr_t)&my_ifr) == -1) | |||
1466 | warn("%s: SIOCSIFXFLAGS", my_ifr.ifr_name); | |||
1467 | } | |||
1468 | ||||
1469 | void | |||
1470 | addaf(const char *vname, int value) | |||
1471 | { | |||
1472 | struct if_afreq ifar; | |||
1473 | ||||
1474 | strlcpy(ifar.ifar_name, ifname, sizeof(ifar.ifar_name)); | |||
1475 | ifar.ifar_af = value; | |||
1476 | if (ioctl(sock, SIOCIFAFATTACH((unsigned long)0x80000000 | ((sizeof(struct if_afreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((171))), (caddr_t)&ifar) == -1) | |||
1477 | warn("%s: SIOCIFAFATTACH", ifar.ifar_name); | |||
1478 | } | |||
1479 | ||||
1480 | void | |||
1481 | removeaf(const char *vname, int value) | |||
1482 | { | |||
1483 | struct if_afreq ifar; | |||
1484 | ||||
1485 | strlcpy(ifar.ifar_name, ifname, sizeof(ifar.ifar_name)); | |||
1486 | ifar.ifar_af = value; | |||
1487 | if (ioctl(sock, SIOCIFAFDETACH((unsigned long)0x80000000 | ((sizeof(struct if_afreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((172))), (caddr_t)&ifar) == -1) | |||
1488 | warn("%s: SIOCIFAFDETACH", ifar.ifar_name); | |||
1489 | } | |||
1490 | ||||
1491 | void | |||
1492 | setia6flags(const char *vname, int value) | |||
1493 | { | |||
1494 | ||||
1495 | if (value < 0) { | |||
1496 | value = -value; | |||
1497 | in6_addreq.ifra_flags &= ~value; | |||
1498 | } else | |||
1499 | in6_addreq.ifra_flags |= value; | |||
1500 | } | |||
1501 | ||||
1502 | void | |||
1503 | setia6pltime(const char *val, int d) | |||
1504 | { | |||
1505 | ||||
1506 | setia6lifetime("pltime", val); | |||
1507 | } | |||
1508 | ||||
1509 | void | |||
1510 | setia6vltime(const char *val, int d) | |||
1511 | { | |||
1512 | ||||
1513 | setia6lifetime("vltime", val); | |||
1514 | } | |||
1515 | ||||
1516 | void | |||
1517 | setia6lifetime(const char *cmd, const char *val) | |||
1518 | { | |||
1519 | const char *errmsg = NULL((void *)0); | |||
1520 | time_t newval, t; | |||
1521 | ||||
1522 | newval = strtonum(val, 0, 1000000, &errmsg); | |||
1523 | if (errmsg) | |||
1524 | errx(1, "invalid %s %s: %s", cmd, val, errmsg); | |||
1525 | ||||
1526 | t = time(NULL((void *)0)); | |||
1527 | ||||
1528 | if (afp->af_af != AF_INET624) | |||
1529 | errx(1, "%s not allowed for this address family", cmd); | |||
1530 | if (strcmp(cmd, "vltime") == 0) { | |||
1531 | in6_addreq.ifra_lifetime.ia6t_expire = t + newval; | |||
1532 | in6_addreq.ifra_lifetime.ia6t_vltime = newval; | |||
1533 | } else if (strcmp(cmd, "pltime") == 0) { | |||
1534 | in6_addreq.ifra_lifetime.ia6t_preferred = t + newval; | |||
1535 | in6_addreq.ifra_lifetime.ia6t_pltime = newval; | |||
1536 | } | |||
1537 | } | |||
1538 | ||||
1539 | void | |||
1540 | setia6eui64(const char *cmd, int val) | |||
1541 | { | |||
1542 | struct ifaddrs *ifap, *ifa; | |||
1543 | const struct sockaddr_in6 *sin6 = NULL((void *)0); | |||
1544 | const struct in6_addr *lladdr = NULL((void *)0); | |||
1545 | struct in6_addr *in6; | |||
1546 | ||||
1547 | if (afp->af_af != AF_INET624) | |||
1548 | errx(1, "%s not allowed for this address family", cmd); | |||
1549 | ||||
1550 | addaf(ifname, AF_INET624); | |||
1551 | ||||
1552 | in6 = (struct in6_addr *)&in6_addreq.ifra_addrifra_ifrau.ifrau_addr.sin6_addr; | |||
1553 | if (memcmp(&in6addr_any.s6_addr__u6_addr.__u6_addr8[8], &in6->s6_addr__u6_addr.__u6_addr8[8], 8) != 0) | |||
1554 | errx(1, "interface index is already filled"); | |||
1555 | if (getifaddrs(&ifap) != 0) | |||
1556 | err(1, "getifaddrs"); | |||
1557 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | |||
1558 | if (ifa->ifa_addr->sa_family == AF_INET624 && | |||
1559 | strcmp(ifa->ifa_name, ifname) == 0) { | |||
1560 | sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr; | |||
1561 | if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe ) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8 [1] & 0xc0) == 0x80))) { | |||
1562 | lladdr = &sin6->sin6_addr; | |||
1563 | break; | |||
1564 | } | |||
1565 | } | |||
1566 | } | |||
1567 | if (!lladdr) | |||
1568 | errx(1, "could not determine link local address"); | |||
1569 | ||||
1570 | memcpy(&in6->s6_addr__u6_addr.__u6_addr8[8], &lladdr->s6_addr__u6_addr.__u6_addr8[8], 8); | |||
1571 | ||||
1572 | freeifaddrs(ifap); | |||
1573 | } | |||
1574 | ||||
1575 | void | |||
1576 | setautoconf(const char *cmd, int val) | |||
1577 | { | |||
1578 | switch (afp->af_af) { | |||
1579 | case AF_INET2: | |||
1580 | setifxflags("inet", val * IFXF_AUTOCONF40x80); | |||
1581 | break; | |||
1582 | case AF_INET624: | |||
1583 | if (val > 0) | |||
1584 | setifxflags("inet6", (IFXF_AUTOCONF60x20 | | |||
1585 | IFXF_AUTOCONF6TEMP0x4)); | |||
1586 | else | |||
1587 | setifxflags("inet6", -IFXF_AUTOCONF60x20); | |||
1588 | break; | |||
1589 | default: | |||
1590 | errx(1, "autoconf not allowed for this address family"); | |||
1591 | } | |||
1592 | } | |||
1593 | ||||
1594 | void | |||
1595 | settemporary(const char *cmd, int val) | |||
1596 | { | |||
1597 | switch (afp->af_af) { | |||
1598 | case AF_INET624: | |||
1599 | setifxflags("inet6", val * IFXF_AUTOCONF6TEMP0x4); | |||
1600 | break; | |||
1601 | default: | |||
1602 | errx(1, "temporary not allowed for this address family"); | |||
1603 | } | |||
1604 | } | |||
1605 | ||||
1606 | #ifndef SMALL | |||
1607 | void | |||
1608 | setifmetric(const char *val, int ignored) | |||
1609 | { | |||
1610 | const char *errmsg = NULL((void *)0); | |||
1611 | ||||
1612 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1613 | ||||
1614 | ifr.ifr_metricifr_ifru.ifru_metric = strtonum(val, 0, INT_MAX0x7fffffff, &errmsg); | |||
1615 | if (errmsg) | |||
1616 | errx(1, "metric %s: %s", val, errmsg); | |||
1617 | if (ioctl(sock, SIOCSIFMETRIC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((24))), (caddr_t)&ifr) == -1) | |||
1618 | warn("SIOCSIFMETRIC"); | |||
1619 | } | |||
1620 | #endif | |||
1621 | ||||
1622 | void | |||
1623 | setifmtu(const char *val, int d) | |||
1624 | { | |||
1625 | const char *errmsg = NULL((void *)0); | |||
1626 | ||||
1627 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1628 | ||||
1629 | ifr.ifr_mtuifr_ifru.ifru_metric = strtonum(val, 0, INT_MAX0x7fffffff, &errmsg); | |||
1630 | if (errmsg) | |||
1631 | errx(1, "mtu %s: %s", val, errmsg); | |||
1632 | if (ioctl(sock, SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((127))), (caddr_t)&ifr) == -1) | |||
1633 | warn("SIOCSIFMTU"); | |||
1634 | } | |||
1635 | ||||
1636 | void | |||
1637 | setifllprio(const char *val, int d) | |||
1638 | { | |||
1639 | const char *errmsg = NULL((void *)0); | |||
1640 | ||||
1641 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1642 | ||||
1643 | ifr.ifr_llprioifr_ifru.ifru_metric = strtonum(val, 0, UCHAR_MAX0xff, &errmsg); | |||
1644 | if (errmsg) | |||
1645 | errx(1, "llprio %s: %s", val, errmsg); | |||
1646 | if (ioctl(sock, SIOCSIFLLPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((181))), (caddr_t)&ifr) == -1) | |||
1647 | warn("SIOCSIFLLPRIO"); | |||
1648 | } | |||
1649 | ||||
1650 | void | |||
1651 | setifgroup(const char *group_name, int dummy) | |||
1652 | { | |||
1653 | struct ifgroupreq ifgr; | |||
1654 | size_t namelen; | |||
1655 | ||||
1656 | memset(&ifgr, 0, sizeof(ifgr)); | |||
1657 | strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ16); | |||
1658 | ||||
1659 | namelen = strlen(group_name); | |||
1660 | if (namelen == 0) | |||
1661 | errx(1, "setifgroup: group name empty"); | |||
1662 | if (namelen >= IFNAMSIZ16) | |||
1663 | errx(1, "setifgroup: group name too long"); | |||
1664 | if (isdigit((unsigned char)group_name[namelen - 1])) | |||
1665 | errx(1, "setifgroup: group names may not end in a digit"); | |||
1666 | ||||
1667 | strlcpy(ifgr.ifgr_groupifgr_ifgru.ifgru_group, group_name, IFNAMSIZ16); | |||
1668 | if (ioctl(sock, SIOCAIFGROUP((unsigned long)0x80000000 | ((sizeof(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((135))), (caddr_t)&ifgr) == -1) { | |||
1669 | if (errno(*__errno()) != EEXIST17) | |||
1670 | err(1,"%s: SIOCAIFGROUP", group_name); | |||
1671 | } | |||
1672 | } | |||
1673 | ||||
1674 | void | |||
1675 | unsetifgroup(const char *group_name, int dummy) | |||
1676 | { | |||
1677 | struct ifgroupreq ifgr; | |||
1678 | ||||
1679 | memset(&ifgr, 0, sizeof(ifgr)); | |||
1680 | strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ16); | |||
1681 | ||||
1682 | if (strlcpy(ifgr.ifgr_groupifgr_ifgru.ifgru_group, group_name, IFNAMSIZ16) >= IFNAMSIZ16) | |||
1683 | errx(1, "unsetifgroup: group name too long"); | |||
1684 | if (ioctl(sock, SIOCDIFGROUP((unsigned long)0x80000000 | ((sizeof(struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((137))), (caddr_t)&ifgr) == -1) | |||
1685 | err(1, "%s: SIOCDIFGROUP", group_name); | |||
1686 | } | |||
1687 | ||||
1688 | const char * | |||
1689 | get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp) | |||
1690 | { | |||
1691 | int len = *lenp, hexstr; | |||
1692 | u_int8_t *p = buf; | |||
1693 | ||||
1694 | hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x'); | |||
1695 | if (hexstr) | |||
1696 | val += 2; | |||
1697 | for (;;) { | |||
1698 | if (*val == '\0') | |||
1699 | break; | |||
1700 | if (sep != NULL((void *)0) && strchr(sep, *val) != NULL((void *)0)) { | |||
1701 | val++; | |||
1702 | break; | |||
1703 | } | |||
1704 | if (hexstr) { | |||
1705 | if (!isxdigit((u_char)val[0]) || | |||
1706 | !isxdigit((u_char)val[1])) { | |||
1707 | warnx("bad hexadecimal digits"); | |||
1708 | return NULL((void *)0); | |||
1709 | } | |||
1710 | } | |||
1711 | if (p > buf + len) { | |||
1712 | if (hexstr) | |||
1713 | warnx("hexadecimal digits too long"); | |||
1714 | else | |||
1715 | warnx("strings too long"); | |||
1716 | return NULL((void *)0); | |||
1717 | } | |||
1718 | if (hexstr) { | |||
1719 | #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10) | |||
1720 | *p++ = (tohex((u_char)val[0]) << 4) | | |||
1721 | tohex((u_char)val[1]); | |||
1722 | #undef tohex | |||
1723 | val += 2; | |||
1724 | } else { | |||
1725 | if (*val == '\\' && | |||
1726 | sep != NULL((void *)0) && strchr(sep, *(val + 1)) != NULL((void *)0)) | |||
1727 | val++; | |||
1728 | *p++ = *val++; | |||
1729 | } | |||
1730 | } | |||
1731 | len = p - buf; | |||
1732 | if (len < *lenp) | |||
1733 | memset(p, 0, *lenp - len); | |||
1734 | *lenp = len; | |||
1735 | return val; | |||
1736 | } | |||
1737 | ||||
1738 | int | |||
1739 | len_string(const u_int8_t *buf, int len) | |||
1740 | { | |||
1741 | int i = 0, hasspc = 0; | |||
1742 | ||||
1743 | if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { | |||
1744 | for (; i < len; i++) { | |||
1745 | /* Only print 7-bit ASCII keys */ | |||
1746 | if (buf[i] & 0x80 || !isprint(buf[i])) | |||
1747 | break; | |||
1748 | if (isspace(buf[i])) | |||
1749 | hasspc++; | |||
1750 | } | |||
1751 | } | |||
1752 | if (i == len) { | |||
1753 | if (hasspc || len == 0) | |||
1754 | return len + 2; | |||
1755 | else | |||
1756 | return len; | |||
1757 | } else | |||
1758 | return (len * 2) + 2; | |||
1759 | } | |||
1760 | ||||
1761 | int | |||
1762 | print_string(const u_int8_t *buf, int len) | |||
1763 | { | |||
1764 | int i = 0, hasspc = 0; | |||
1765 | ||||
1766 | if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') { | |||
1767 | for (; i < len; i++) { | |||
1768 | /* Only print 7-bit ASCII keys */ | |||
1769 | if (buf[i] & 0x80 || !isprint(buf[i])) | |||
1770 | break; | |||
1771 | if (isspace(buf[i])) | |||
1772 | hasspc++; | |||
1773 | } | |||
1774 | } | |||
1775 | if (i == len) { | |||
1776 | if (hasspc || len == 0) { | |||
1777 | printf("\"%.*s\"", len, buf); | |||
1778 | return len + 2; | |||
1779 | } else { | |||
1780 | printf("%.*s", len, buf); | |||
1781 | return len; | |||
1782 | } | |||
1783 | } else { | |||
1784 | printf("0x"); | |||
1785 | for (i = 0; i < len; i++) | |||
1786 | printf("%02x", buf[i]); | |||
1787 | return (len * 2) + 2; | |||
1788 | } | |||
1789 | } | |||
1790 | ||||
1791 | void | |||
1792 | setifnwid(const char *val, int d) | |||
1793 | { | |||
1794 | struct ieee80211_nwid nwid; | |||
1795 | int len; | |||
1796 | ||||
1797 | if (joinlen != 0) { | |||
1798 | errx(1, "nwid and join may not be used at the same time"); | |||
1799 | } | |||
1800 | ||||
1801 | if (nwidlen != 0) { | |||
1802 | errx(1, "nwid may not be specified twice"); | |||
1803 | } | |||
1804 | ||||
1805 | if (d != 0) { | |||
1806 | /* no network id is especially desired */ | |||
1807 | memset(&nwid, 0, sizeof(nwid)); | |||
1808 | len = 0; | |||
1809 | } else { | |||
1810 | len = sizeof(nwid.i_nwid); | |||
1811 | if (get_string(val, NULL((void *)0), nwid.i_nwid, &len) == NULL((void *)0)) | |||
1812 | return; | |||
1813 | } | |||
1814 | nwidlen = nwid.i_len = len; | |||
1815 | (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1816 | memcpy(nwidname, nwid.i_nwid, len); | |||
1817 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&nwid; | |||
1818 | if (ioctl(sock, SIOCS80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((230))), (caddr_t)&ifr) == -1) | |||
1819 | warn("SIOCS80211NWID"); | |||
1820 | } | |||
1821 | ||||
1822 | ||||
1823 | void | |||
1824 | process_join_commands(void) | |||
1825 | { | |||
1826 | if (!(actions & A_JOIN0x0020)) | |||
1827 | return; | |||
1828 | ||||
1829 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join; | |||
1830 | if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((255))), (caddr_t)&ifr) == -1) | |||
1831 | err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); | |||
1832 | } | |||
1833 | ||||
1834 | void | |||
1835 | setifjoin(const char *val, int d) | |||
1836 | { | |||
1837 | int len; | |||
1838 | ||||
1839 | if (nwidlen != 0) { | |||
1840 | errx(1, "nwid and join may not be used at the same time"); | |||
1841 | } | |||
1842 | ||||
1843 | if (joinlen != 0) { | |||
1844 | errx(1, "join may not be specified twice"); | |||
1845 | } | |||
1846 | ||||
1847 | if (d != 0) { | |||
1848 | /* no network id is especially desired */ | |||
1849 | memset(&join, 0, sizeof(join)); | |||
1850 | len = 0; | |||
1851 | } else { | |||
1852 | len = sizeof(join.i_nwid); | |||
1853 | if (get_string(val, NULL((void *)0), join.i_nwid, &len) == NULL((void *)0)) | |||
1854 | return; | |||
1855 | if (len == 0) | |||
1856 | join.i_flags |= IEEE80211_JOIN_ANY0x80; | |||
1857 | } | |||
1858 | joinlen = join.i_len = len; | |||
1859 | (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1860 | memcpy(joinname, join.i_nwid, len); | |||
1861 | ||||
1862 | actions |= A_JOIN0x0020; | |||
1863 | } | |||
1864 | ||||
1865 | void | |||
1866 | delifjoin(const char *val, int d) | |||
1867 | { | |||
1868 | struct ieee80211_join join; | |||
1869 | int len; | |||
1870 | ||||
1871 | memset(&join, 0, sizeof(join)); | |||
1872 | len = 0; | |||
1873 | join.i_flags |= IEEE80211_JOIN_DEL0x04; | |||
1874 | ||||
1875 | if (d == -1) { | |||
1876 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join; | |||
1877 | if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((255))), (caddr_t)&ifr) == -1) | |||
1878 | err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); | |||
1879 | } | |||
1880 | ||||
1881 | len = sizeof(join.i_nwid); | |||
1882 | if (get_string(val, NULL((void *)0), join.i_nwid, &len) == NULL((void *)0)) | |||
1883 | return; | |||
1884 | join.i_len = len; | |||
1885 | if (len == 0) | |||
1886 | join.i_flags |= IEEE80211_JOIN_ANY0x80; | |||
1887 | (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
1888 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join; | |||
1889 | if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((255))), (caddr_t)&ifr) == -1) | |||
1890 | err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); | |||
1891 | } | |||
1892 | ||||
1893 | void | |||
1894 | delifjoinlist(const char *val, int d) | |||
1895 | { | |||
1896 | struct ieee80211_join join; | |||
1897 | ||||
1898 | memset(&join, 0, sizeof(join)); | |||
1899 | join.i_flags |= (IEEE80211_JOIN_DEL0x04 | IEEE80211_JOIN_DEL_ALL0x100); | |||
1900 | ||||
1901 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join; | |||
1902 | if (ioctl(sock, SIOCS80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((255))), (caddr_t)&ifr) == -1) | |||
1903 | err(1, "%s: SIOCS80211JOIN", ifr.ifr_name); | |||
1904 | } | |||
1905 | ||||
1906 | void | |||
1907 | setifbssid(const char *val, int d) | |||
1908 | { | |||
1909 | ||||
1910 | struct ieee80211_bssid bssid; | |||
1911 | struct ether_addr *ea; | |||
1912 | ||||
1913 | if (d != 0) { | |||
1914 | /* no BSSID is especially desired */ | |||
1915 | memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid)); | |||
1916 | } else { | |||
1917 | ea = ether_aton((char*)val); | |||
1918 | if (ea == NULL((void *)0)) { | |||
1919 | warnx("malformed BSSID: %s", val); | |||
1920 | return; | |||
1921 | } | |||
1922 | memcpy(&bssid.i_bssid, ea->ether_addr_octet, | |||
1923 | sizeof(bssid.i_bssid)); | |||
1924 | } | |||
1925 | strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name)); | |||
1926 | if (ioctl(sock, SIOCS80211BSSID((unsigned long)0x80000000 | ((sizeof(struct ieee80211_bssid) & 0x1fff) << 16) | ((('i')) << 8) | ((240))), &bssid) == -1) | |||
1927 | warn("%s: SIOCS80211BSSID", bssid.i_name); | |||
1928 | } | |||
1929 | ||||
1930 | void | |||
1931 | setifnwkey(const char *val, int d) | |||
1932 | { | |||
1933 | int i, len; | |||
1934 | struct ieee80211_nwkey nwkey; | |||
1935 | u_int8_t keybuf[IEEE80211_WEP_NKID4][16]; | |||
1936 | ||||
1937 | bzero(&nwkey, sizeof(nwkey)); | |||
1938 | bzero(&keybuf, sizeof(keybuf)); | |||
1939 | ||||
1940 | nwkey.i_wepon = IEEE80211_NWKEY_WEP1; | |||
1941 | nwkey.i_defkid = 1; | |||
1942 | if (d == -1) { | |||
1943 | /* disable WEP encryption */ | |||
1944 | nwkey.i_wepon = IEEE80211_NWKEY_OPEN0; | |||
1945 | i = 0; | |||
1946 | } else if (strcasecmp("persist", val) == 0) { | |||
1947 | /* use all values from persistent memory */ | |||
1948 | nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST0x100; | |||
1949 | nwkey.i_defkid = 0; | |||
1950 | for (i = 0; i < IEEE80211_WEP_NKID4; i++) | |||
1951 | nwkey.i_key[i].i_keylen = -1; | |||
1952 | } else if (strncasecmp("persist:", val, 8) == 0) { | |||
1953 | val += 8; | |||
1954 | /* program keys in persistent memory */ | |||
1955 | nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST0x100; | |||
1956 | goto set_nwkey; | |||
1957 | } else { | |||
1958 | set_nwkey: | |||
1959 | if (isdigit((unsigned char)val[0]) && val[1] == ':') { | |||
1960 | /* specifying a full set of four keys */ | |||
1961 | nwkey.i_defkid = val[0] - '0'; | |||
1962 | val += 2; | |||
1963 | for (i = 0; i < IEEE80211_WEP_NKID4; i++) { | |||
1964 | len = sizeof(keybuf[i]); | |||
1965 | val = get_string(val, ",", keybuf[i], &len); | |||
1966 | if (val == NULL((void *)0)) | |||
1967 | return; | |||
1968 | nwkey.i_key[i].i_keylen = len; | |||
1969 | nwkey.i_key[i].i_keydat = keybuf[i]; | |||
1970 | } | |||
1971 | if (*val != '\0') { | |||
1972 | warnx("SIOCS80211NWKEY: too many keys."); | |||
1973 | return; | |||
1974 | } | |||
1975 | } else { | |||
1976 | /* | |||
1977 | * length of each key must be either a 5 | |||
1978 | * character ASCII string or 10 hex digits for | |||
1979 | * 40 bit encryption, or 13 character ASCII | |||
1980 | * string or 26 hex digits for 128 bit | |||
1981 | * encryption. | |||
1982 | */ | |||
1983 | int j; | |||
1984 | char *tmp = NULL((void *)0); | |||
1985 | size_t vlen = strlen(val); | |||
1986 | switch(vlen) { | |||
1987 | case 10: | |||
1988 | case 26: | |||
1989 | /* 0x must be missing for these lengths */ | |||
1990 | j = asprintf(&tmp, "0x%s", val); | |||
1991 | if (j == -1) { | |||
1992 | warnx("malloc failed"); | |||
1993 | return; | |||
1994 | } | |||
1995 | val = tmp; | |||
1996 | break; | |||
1997 | case 12: | |||
1998 | case 28: | |||
1999 | case 5: | |||
2000 | case 13: | |||
2001 | /* 0xkey or string case - all is ok */ | |||
2002 | break; | |||
2003 | default: | |||
2004 | warnx("Invalid WEP key length"); | |||
2005 | return; | |||
2006 | } | |||
2007 | len = sizeof(keybuf[0]); | |||
2008 | val = get_string(val, NULL((void *)0), keybuf[0], &len); | |||
2009 | free(tmp); | |||
2010 | if (val == NULL((void *)0)) | |||
2011 | return; | |||
2012 | nwkey.i_key[0].i_keylen = len; | |||
2013 | nwkey.i_key[0].i_keydat = keybuf[0]; | |||
2014 | i = 1; | |||
2015 | } | |||
2016 | } | |||
2017 | (void)strlcpy(nwkey.i_name, ifname, sizeof(nwkey.i_name)); | |||
2018 | ||||
2019 | if (actions & A_JOIN0x0020) { | |||
2020 | memcpy(&join.i_nwkey, &nwkey, sizeof(join.i_nwkey)); | |||
2021 | join.i_flags |= IEEE80211_JOIN_NWKEY0x08; | |||
2022 | return; | |||
2023 | } | |||
2024 | ||||
2025 | if (ioctl(sock, SIOCS80211NWKEY((unsigned long)0x80000000 | ((sizeof(struct ieee80211_nwkey) & 0x1fff) << 16) | ((('i')) << 8) | ((232))), (caddr_t)&nwkey) == -1) | |||
2026 | err(1, "%s: SIOCS80211NWKEY", nwkey.i_name); | |||
2027 | } | |||
2028 | ||||
2029 | void | |||
2030 | setifwpa(const char *val, int d) | |||
2031 | { | |||
2032 | struct ieee80211_wpaparams wpa; | |||
2033 | ||||
2034 | memset(&wpa, 0, sizeof(wpa)); | |||
2035 | (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); | |||
2036 | /* Don't read current values. The kernel will set defaults. */ | |||
2037 | wpa.i_enabled = d; | |||
2038 | ||||
2039 | if (actions & A_JOIN0x0020) { | |||
2040 | join.i_wpaparams.i_enabled = d; | |||
2041 | join.i_flags |= IEEE80211_JOIN_WPA0x10; | |||
2042 | return; | |||
2043 | } | |||
2044 | ||||
2045 | if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams ) & 0x1fff) << 16) | ((('i')) << 8) | ((247)) ), (caddr_t)&wpa) == -1) | |||
2046 | err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); | |||
2047 | } | |||
2048 | ||||
2049 | void | |||
2050 | setifwpaprotos(const char *val, int d) | |||
2051 | { | |||
2052 | struct ieee80211_wpaparams wpa; | |||
2053 | char *optlist, *str; | |||
2054 | u_int rval = 0; | |||
2055 | ||||
2056 | if ((optlist = strdup(val)) == NULL((void *)0)) | |||
2057 | err(1, "strdup"); | |||
2058 | str = strtok(optlist, ","); | |||
2059 | while (str != NULL((void *)0)) { | |||
2060 | if (strcasecmp(str, "wpa1") == 0) | |||
2061 | rval |= IEEE80211_WPA_PROTO_WPA10x01; | |||
2062 | else if (strcasecmp(str, "wpa2") == 0) | |||
2063 | rval |= IEEE80211_WPA_PROTO_WPA20x02; | |||
2064 | else | |||
2065 | errx(1, "wpaprotos: unknown protocol: %s", str); | |||
2066 | str = strtok(NULL((void *)0), ","); | |||
2067 | } | |||
2068 | free(optlist); | |||
2069 | ||||
2070 | if (actions & A_JOIN0x0020) { | |||
2071 | join.i_wpaparams.i_protos = rval; | |||
2072 | join.i_flags |= IEEE80211_JOIN_WPA0x10; | |||
2073 | return; | |||
2074 | } | |||
2075 | ||||
2076 | memset(&wpa, 0, sizeof(wpa)); | |||
2077 | (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); | |||
2078 | if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_wpaparams) & 0x1fff) << 16) | ((( 'i')) << 8) | ((248))), (caddr_t)&wpa) == -1) | |||
2079 | err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); | |||
2080 | wpa.i_protos = rval; | |||
2081 | /* Let the kernel set up the appropriate default ciphers. */ | |||
2082 | wpa.i_ciphers = 0; | |||
2083 | wpa.i_groupcipher = 0; | |||
2084 | ||||
2085 | if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams ) & 0x1fff) << 16) | ((('i')) << 8) | ((247)) ), (caddr_t)&wpa) == -1) | |||
2086 | err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); | |||
2087 | } | |||
2088 | ||||
2089 | void | |||
2090 | setifwpaakms(const char *val, int d) | |||
2091 | { | |||
2092 | struct ieee80211_wpaparams wpa; | |||
2093 | char *optlist, *str; | |||
2094 | u_int rval = 0; | |||
2095 | ||||
2096 | if ((optlist = strdup(val)) == NULL((void *)0)) | |||
2097 | err(1, "strdup"); | |||
2098 | str = strtok(optlist, ","); | |||
2099 | while (str != NULL((void *)0)) { | |||
2100 | if (strcasecmp(str, "psk") == 0) | |||
2101 | rval |= IEEE80211_WPA_AKM_PSK0x01; | |||
2102 | else if (strcasecmp(str, "802.1x") == 0) | |||
2103 | rval |= IEEE80211_WPA_AKM_8021X0x02; | |||
2104 | else | |||
2105 | errx(1, "wpaakms: unknown akm: %s", str); | |||
2106 | str = strtok(NULL((void *)0), ","); | |||
2107 | } | |||
2108 | free(optlist); | |||
2109 | ||||
2110 | if (actions & A_JOIN0x0020) { | |||
2111 | join.i_wpaparams.i_akms = rval; | |||
2112 | join.i_wpaparams.i_enabled = | |||
2113 | ((rval & IEEE80211_WPA_AKM_8021X0x02) != 0); | |||
2114 | join.i_flags |= IEEE80211_JOIN_WPA0x10; | |||
2115 | return; | |||
2116 | } | |||
2117 | ||||
2118 | memset(&wpa, 0, sizeof(wpa)); | |||
2119 | (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); | |||
2120 | if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_wpaparams) & 0x1fff) << 16) | ((( 'i')) << 8) | ((248))), (caddr_t)&wpa) == -1) | |||
2121 | err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); | |||
2122 | wpa.i_akms = rval; | |||
2123 | /* Enable WPA for 802.1x here. PSK case is handled in setifwpakey(). */ | |||
2124 | wpa.i_enabled = ((rval & IEEE80211_WPA_AKM_8021X0x02) != 0); | |||
2125 | ||||
2126 | if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams ) & 0x1fff) << 16) | ((('i')) << 8) | ((247)) ), (caddr_t)&wpa) == -1) | |||
2127 | err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); | |||
2128 | } | |||
2129 | ||||
2130 | static const struct { | |||
2131 | const char *name; | |||
2132 | u_int cipher; | |||
2133 | } ciphers[] = { | |||
2134 | { "usegroup", IEEE80211_WPA_CIPHER_USEGROUP0x01 }, | |||
2135 | { "wep40", IEEE80211_WPA_CIPHER_WEP400x02 }, | |||
2136 | { "tkip", IEEE80211_WPA_CIPHER_TKIP0x04 }, | |||
2137 | { "ccmp", IEEE80211_WPA_CIPHER_CCMP0x08 }, | |||
2138 | { "wep104", IEEE80211_WPA_CIPHER_WEP1040x10 } | |||
2139 | }; | |||
2140 | ||||
2141 | u_int | |||
2142 | getwpacipher(const char *name) | |||
2143 | { | |||
2144 | int i; | |||
2145 | ||||
2146 | for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) | |||
2147 | if (strcasecmp(name, ciphers[i].name) == 0) | |||
2148 | return ciphers[i].cipher; | |||
2149 | return IEEE80211_WPA_CIPHER_NONE0x00; | |||
2150 | } | |||
2151 | ||||
2152 | void | |||
2153 | setifwpaciphers(const char *val, int d) | |||
2154 | { | |||
2155 | struct ieee80211_wpaparams wpa; | |||
2156 | char *optlist, *str; | |||
2157 | u_int rval = 0; | |||
2158 | ||||
2159 | if ((optlist = strdup(val)) == NULL((void *)0)) | |||
2160 | err(1, "strdup"); | |||
2161 | str = strtok(optlist, ","); | |||
2162 | while (str != NULL((void *)0)) { | |||
2163 | u_int cipher = getwpacipher(str); | |||
2164 | if (cipher == IEEE80211_WPA_CIPHER_NONE0x00) | |||
2165 | errx(1, "wpaciphers: unknown cipher: %s", str); | |||
2166 | ||||
2167 | rval |= cipher; | |||
2168 | str = strtok(NULL((void *)0), ","); | |||
2169 | } | |||
2170 | free(optlist); | |||
2171 | ||||
2172 | if (actions & A_JOIN0x0020) { | |||
2173 | join.i_wpaparams.i_ciphers = rval; | |||
2174 | join.i_flags |= IEEE80211_JOIN_WPA0x10; | |||
2175 | return; | |||
2176 | } | |||
2177 | ||||
2178 | memset(&wpa, 0, sizeof(wpa)); | |||
2179 | (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); | |||
2180 | if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_wpaparams) & 0x1fff) << 16) | ((( 'i')) << 8) | ((248))), (caddr_t)&wpa) == -1) | |||
2181 | err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); | |||
2182 | wpa.i_ciphers = rval; | |||
2183 | ||||
2184 | if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams ) & 0x1fff) << 16) | ((('i')) << 8) | ((247)) ), (caddr_t)&wpa) == -1) | |||
2185 | err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); | |||
2186 | } | |||
2187 | ||||
2188 | void | |||
2189 | setifwpagroupcipher(const char *val, int d) | |||
2190 | { | |||
2191 | struct ieee80211_wpaparams wpa; | |||
2192 | u_int cipher; | |||
2193 | ||||
2194 | cipher = getwpacipher(val); | |||
2195 | if (cipher == IEEE80211_WPA_CIPHER_NONE0x00) | |||
2196 | errx(1, "wpagroupcipher: unknown cipher: %s", val); | |||
2197 | ||||
2198 | memset(&wpa, 0, sizeof(wpa)); | |||
2199 | (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); | |||
2200 | if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_wpaparams) & 0x1fff) << 16) | ((( 'i')) << 8) | ((248))), (caddr_t)&wpa) == -1) | |||
2201 | err(1, "%s: SIOCG80211WPAPARMS", wpa.i_name); | |||
2202 | wpa.i_groupcipher = cipher; | |||
2203 | ||||
2204 | if (actions & A_JOIN0x0020) { | |||
2205 | join.i_wpaparams.i_groupcipher = cipher; | |||
2206 | join.i_flags |= IEEE80211_JOIN_WPA0x10; | |||
2207 | return; | |||
2208 | } | |||
2209 | ||||
2210 | if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams ) & 0x1fff) << 16) | ((('i')) << 8) | ((247)) ), (caddr_t)&wpa) == -1) | |||
2211 | err(1, "%s: SIOCS80211WPAPARMS", wpa.i_name); | |||
2212 | } | |||
2213 | ||||
2214 | void | |||
2215 | setifwpakey(const char *val, int d) | |||
2216 | { | |||
2217 | struct ieee80211_wpaparams wpa; | |||
2218 | struct ieee80211_wpapsk psk; | |||
2219 | struct ieee80211_nwid nwid; | |||
2220 | int passlen; | |||
2221 | ||||
2222 | memset(&psk, 0, sizeof(psk)); | |||
2223 | if (d != -1) { | |||
2224 | memset(&ifr, 0, sizeof(ifr)); | |||
2225 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&nwid; | |||
2226 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
2227 | ||||
2228 | /* Use the value specified in 'join' or 'nwid' */ | |||
2229 | if (joinlen != 0) { | |||
2230 | memcpy(nwid.i_nwid, joinname, joinlen); | |||
2231 | nwid.i_len = joinlen; | |||
2232 | } else if (nwidlen != 0) { | |||
2233 | memcpy(nwid.i_nwid, nwidname, nwidlen); | |||
2234 | nwid.i_len = nwidlen; | |||
2235 | } else { | |||
2236 | warnx("no nwid or join command, guessing nwid to use"); | |||
2237 | ||||
2238 | if (ioctl(sock, SIOCG80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((231))), (caddr_t)&ifr) == -1) | |||
2239 | err(1, "%s: SIOCG80211NWID", ifr.ifr_name); | |||
2240 | } | |||
2241 | ||||
2242 | passlen = strlen(val); | |||
2243 | if (passlen == 2 + 2 * sizeof(psk.i_psk) && | |||
2244 | val[0] == '0' && val[1] == 'x') { | |||
2245 | /* Parse a WPA hex key (must be full-length) */ | |||
2246 | passlen = sizeof(psk.i_psk); | |||
2247 | val = get_string(val, NULL((void *)0), psk.i_psk, &passlen); | |||
2248 | if (val == NULL((void *)0) || passlen != sizeof(psk.i_psk)) | |||
2249 | errx(1, "wpakey: invalid pre-shared key"); | |||
2250 | } else { | |||
2251 | /* Parse a WPA passphrase */ | |||
2252 | if (passlen < 8 || passlen > 63) | |||
2253 | errx(1, "wpakey: passphrase must be between " | |||
2254 | "8 and 63 characters"); | |||
2255 | if (nwid.i_len == 0) | |||
2256 | errx(1, "wpakey: nwid not set"); | |||
2257 | if (pkcs5_pbkdf2(val, passlen, nwid.i_nwid, nwid.i_len, | |||
2258 | psk.i_psk, sizeof(psk.i_psk), 4096) != 0) | |||
2259 | errx(1, "wpakey: passphrase hashing failed"); | |||
2260 | } | |||
2261 | psk.i_enabled = 1; | |||
2262 | } else | |||
2263 | psk.i_enabled = 0; | |||
2264 | ||||
2265 | (void)strlcpy(psk.i_name, ifname, sizeof(psk.i_name)); | |||
2266 | ||||
2267 | if (actions & A_JOIN0x0020) { | |||
2268 | memcpy(&join.i_wpapsk, &psk, sizeof(join.i_wpapsk)); | |||
2269 | join.i_flags |= IEEE80211_JOIN_WPAPSK0x20; | |||
2270 | if (!join.i_wpaparams.i_enabled) | |||
2271 | setifwpa(NULL((void *)0), join.i_wpapsk.i_enabled); | |||
2272 | return; | |||
2273 | } | |||
2274 | ||||
2275 | if (ioctl(sock, SIOCS80211WPAPSK((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpapsk ) & 0x1fff) << 16) | ((('i')) << 8) | ((245)) ), (caddr_t)&psk) == -1) | |||
2276 | err(1, "%s: SIOCS80211WPAPSK", psk.i_name); | |||
2277 | ||||
2278 | /* And ... automatically enable or disable WPA */ | |||
2279 | memset(&wpa, 0, sizeof(wpa)); | |||
2280 | (void)strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); | |||
2281 | if (ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_wpaparams) & 0x1fff) << 16) | ((( 'i')) << 8) | ((248))), (caddr_t)&wpa) == -1) | |||
2282 | err(1, "%s: SIOCG80211WPAPARMS", psk.i_name); | |||
2283 | wpa.i_enabled = psk.i_enabled; | |||
2284 | if (ioctl(sock, SIOCS80211WPAPARMS((unsigned long)0x80000000 | ((sizeof(struct ieee80211_wpaparams ) & 0x1fff) << 16) | ((('i')) << 8) | ((247)) ), (caddr_t)&wpa) == -1) | |||
2285 | err(1, "%s: SIOCS80211WPAPARMS", psk.i_name); | |||
2286 | } | |||
2287 | ||||
2288 | void | |||
2289 | setifchan(const char *val, int d) | |||
2290 | { | |||
2291 | struct ieee80211chanreq channel; | |||
2292 | const char *errstr; | |||
2293 | int chan; | |||
2294 | ||||
2295 | if (val == NULL((void *)0)) { | |||
2296 | if (shownet80211chans || shownet80211nodes) | |||
2297 | usage(); | |||
2298 | shownet80211chans = 1; | |||
2299 | return; | |||
2300 | } | |||
2301 | if (d != 0) | |||
2302 | chan = IEEE80211_CHAN_ANY0xffff; | |||
2303 | else { | |||
2304 | chan = strtonum(val, 1, 256, &errstr); | |||
2305 | if (errstr) { | |||
2306 | warnx("invalid channel %s: %s", val, errstr); | |||
2307 | return; | |||
2308 | } | |||
2309 | } | |||
2310 | ||||
2311 | strlcpy(channel.i_name, ifname, sizeof(channel.i_name)); | |||
2312 | channel.i_channel = (u_int16_t)chan; | |||
2313 | if (ioctl(sock, SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq ) & 0x1fff) << 16) | ((('i')) << 8) | ((238)) ), (caddr_t)&channel) == -1) | |||
2314 | warn("%s: SIOCS80211CHANNEL", channel.i_name); | |||
2315 | } | |||
2316 | ||||
2317 | void | |||
2318 | setifscan(const char *val, int d) | |||
2319 | { | |||
2320 | if (shownet80211chans || shownet80211nodes) | |||
2321 | usage(); | |||
2322 | shownet80211nodes = 1; | |||
2323 | } | |||
2324 | ||||
2325 | #ifndef SMALL | |||
2326 | ||||
2327 | void | |||
2328 | setifnwflag(const char *val, int d) | |||
2329 | { | |||
2330 | static const struct ieee80211_flags nwflags[] = IEEE80211_FLAGS{ { "hidenwid", 0x00000001 }, { "nobridge", 0x00000002 }, { "stayauth" , 0x00000004 }, { "nomimo", 0x00000008 } }; | |||
2331 | u_int i, flag = 0; | |||
2332 | ||||
2333 | for (i = 0; i < (sizeof(nwflags) / sizeof(nwflags[0])); i++) { | |||
2334 | if (strcmp(val, nwflags[i].f_name) == 0) { | |||
2335 | flag = nwflags[i].f_flag; | |||
2336 | break; | |||
2337 | } | |||
2338 | } | |||
2339 | if (flag == 0) | |||
2340 | errx(1, "Invalid nwflag: %s", val); | |||
2341 | ||||
2342 | if (ioctl(sock, SIOCG80211FLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((216))), (caddr_t)&ifr) != 0) | |||
2343 | err(1, "%s: SIOCG80211FLAGS", ifr.ifr_name); | |||
2344 | ||||
2345 | if (d) | |||
2346 | ifr.ifr_flagsifr_ifru.ifru_flags &= ~flag; | |||
2347 | else | |||
2348 | ifr.ifr_flagsifr_ifru.ifru_flags |= flag; | |||
2349 | ||||
2350 | if (ioctl(sock, SIOCS80211FLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((217))), (caddr_t)&ifr) != 0) | |||
2351 | err(1, "%s: SIOCS80211FLAGS", ifr.ifr_name); | |||
2352 | } | |||
2353 | ||||
2354 | void | |||
2355 | unsetifnwflag(const char *val, int d) | |||
2356 | { | |||
2357 | setifnwflag(val, 1); | |||
2358 | } | |||
2359 | ||||
2360 | void | |||
2361 | setifpowersave(const char *val, int d) | |||
2362 | { | |||
2363 | struct ieee80211_power power; | |||
2364 | const char *errmsg = NULL((void *)0); | |||
2365 | ||||
2366 | (void)strlcpy(power.i_name, ifname, sizeof(power.i_name)); | |||
2367 | if (ioctl(sock, SIOCG80211POWER(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_power) & 0x1fff) << 16) | ((('i') ) << 8) | ((235))), (caddr_t)&power) == -1) { | |||
2368 | warn("%s: SIOCG80211POWER", power.i_name); | |||
2369 | return; | |||
2370 | } | |||
2371 | ||||
2372 | if (d != -1 && val != NULL((void *)0)) { | |||
2373 | power.i_maxsleep = strtonum(val, 0, INT_MAX0x7fffffff, &errmsg); | |||
2374 | if (errmsg) | |||
2375 | errx(1, "powersave %s: %s", val, errmsg); | |||
2376 | } | |||
2377 | ||||
2378 | power.i_enabled = d == -1 ? 0 : 1; | |||
2379 | if (ioctl(sock, SIOCS80211POWER((unsigned long)0x80000000 | ((sizeof(struct ieee80211_power) & 0x1fff) << 16) | ((('i')) << 8) | ((234))), (caddr_t)&power) == -1) | |||
2380 | warn("%s: SIOCS80211POWER", power.i_name); | |||
2381 | } | |||
2382 | #endif | |||
2383 | ||||
2384 | void | |||
2385 | print_cipherset(u_int32_t cipherset) | |||
2386 | { | |||
2387 | const char *sep = ""; | |||
2388 | int i; | |||
2389 | ||||
2390 | if (cipherset == IEEE80211_WPA_CIPHER_NONE0x00) { | |||
2391 | printf("none"); | |||
2392 | return; | |||
2393 | } | |||
2394 | for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); i++) { | |||
2395 | if (cipherset & ciphers[i].cipher) { | |||
2396 | printf("%s%s", sep, ciphers[i].name); | |||
2397 | sep = ","; | |||
2398 | } | |||
2399 | } | |||
2400 | } | |||
2401 | ||||
2402 | static void | |||
2403 | print_assoc_failures(uint32_t assoc_fail) | |||
2404 | { | |||
2405 | /* Filter out the most obvious failure cases. */ | |||
2406 | assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_ESSID0x10; | |||
2407 | if (assoc_fail & IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY0x04) | |||
2408 | assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_WPA_PROTO0x40; | |||
2409 | assoc_fail &= ~IEEE80211_NODEREQ_ASSOCFAIL_PRIVACY0x04; | |||
2410 | ||||
2411 | if (assoc_fail == 0) | |||
2412 | return; | |||
2413 | ||||
2414 | printb_status(assoc_fail, IEEE80211_NODEREQ_ASSOCFAIL_BITS"\20\1!CHAN\2!IBSS\3!PRIVACY\4!BASICRATE\5!ESSID\6!BSSID\7!WPAPROTO" "\10!WPAKEY"); | |||
2415 | } | |||
2416 | ||||
2417 | void | |||
2418 | ieee80211_status(void) | |||
2419 | { | |||
2420 | int len, inwid, ijoin, inwkey, ipsk, ichan, ipwr; | |||
2421 | int ibssid, iwpa, assocfail = 0; | |||
2422 | struct ieee80211_nwid nwid; | |||
2423 | struct ieee80211_join join; | |||
2424 | struct ieee80211_nwkey nwkey; | |||
2425 | struct ieee80211_wpapsk psk; | |||
2426 | struct ieee80211_power power; | |||
2427 | struct ieee80211chanreq channel; | |||
2428 | struct ieee80211_bssid bssid; | |||
2429 | struct ieee80211_wpaparams wpa; | |||
2430 | struct ieee80211_nodereq nr; | |||
2431 | u_int8_t zero_bssid[IEEE80211_ADDR_LEN6]; | |||
2432 | struct ether_addr ea; | |||
2433 | ||||
2434 | /* get current status via ioctls */ | |||
2435 | memset(&ifr, 0, sizeof(ifr)); | |||
2436 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&nwid; | |||
2437 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
2438 | inwid = ioctl(sock, SIOCG80211NWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((231))), (caddr_t)&ifr); | |||
2439 | ||||
2440 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&join; | |||
2441 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
2442 | ijoin = ioctl(sock, SIOCG80211JOIN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((0))), (caddr_t)&ifr); | |||
2443 | ||||
2444 | memset(&nwkey, 0, sizeof(nwkey)); | |||
2445 | strlcpy(nwkey.i_name, ifname, sizeof(nwkey.i_name)); | |||
2446 | inwkey = ioctl(sock, SIOCG80211NWKEY(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_nwkey) & 0x1fff) << 16) | ((('i') ) << 8) | ((233))), (caddr_t)&nwkey); | |||
2447 | ||||
2448 | memset(&psk, 0, sizeof(psk)); | |||
2449 | strlcpy(psk.i_name, ifname, sizeof(psk.i_name)); | |||
2450 | ipsk = ioctl(sock, SIOCG80211WPAPSK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_wpapsk) & 0x1fff) << 16) | ((('i' )) << 8) | ((246))), (caddr_t)&psk); | |||
2451 | ||||
2452 | memset(&power, 0, sizeof(power)); | |||
2453 | strlcpy(power.i_name, ifname, sizeof(power.i_name)); | |||
2454 | ipwr = ioctl(sock, SIOCG80211POWER(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_power) & 0x1fff) << 16) | ((('i') ) << 8) | ((235))), &power); | |||
2455 | ||||
2456 | memset(&channel, 0, sizeof(channel)); | |||
2457 | strlcpy(channel.i_name, ifname, sizeof(channel.i_name)); | |||
2458 | ichan = ioctl(sock, SIOCG80211CHANNEL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211chanreq) & 0x1fff) << 16) | ((('i' )) << 8) | ((239))), (caddr_t)&channel); | |||
2459 | ||||
2460 | memset(&bssid, 0, sizeof(bssid)); | |||
2461 | strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name)); | |||
2462 | ibssid = ioctl(sock, SIOCG80211BSSID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_bssid) & 0x1fff) << 16) | ((('i') ) << 8) | ((241))), &bssid); | |||
2463 | ||||
2464 | memset(&wpa, 0, sizeof(wpa)); | |||
2465 | strlcpy(wpa.i_name, ifname, sizeof(wpa.i_name)); | |||
2466 | iwpa = ioctl(sock, SIOCG80211WPAPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_wpaparams) & 0x1fff) << 16) | ((( 'i')) << 8) | ((248))), &wpa); | |||
2467 | ||||
2468 | /* check if any ieee80211 option is active */ | |||
2469 | if (inwid == 0 || ijoin == 0 || inwkey == 0 || ipsk == 0 || | |||
2470 | ipwr == 0 || ichan == 0 || ibssid == 0 || iwpa == 0) | |||
2471 | fputs("\tieee80211:", stdout(&__sF[1])); | |||
2472 | else | |||
2473 | return; | |||
2474 | ||||
2475 | if (inwid == 0) { | |||
2476 | /* nwid.i_nwid is not NUL terminated. */ | |||
2477 | len = nwid.i_len; | |||
2478 | if (len > IEEE80211_NWID_LEN32) | |||
2479 | len = IEEE80211_NWID_LEN32; | |||
2480 | if (ijoin == 0 && join.i_flags & IEEE80211_JOIN_FOUND0x02) | |||
2481 | fputs(" join ", stdout(&__sF[1])); | |||
2482 | else | |||
2483 | fputs(" nwid ", stdout(&__sF[1])); | |||
2484 | print_string(nwid.i_nwid, len); | |||
2485 | } | |||
2486 | ||||
2487 | if (ichan == 0 && channel.i_channel != 0 && | |||
2488 | channel.i_channel != IEEE80211_CHAN_ANY0xffff) | |||
2489 | printf(" chan %u", channel.i_channel); | |||
2490 | ||||
2491 | memset(&zero_bssid, 0, sizeof(zero_bssid)); | |||
2492 | if (ibssid == 0 && | |||
2493 | memcmp(bssid.i_bssid, zero_bssid, IEEE80211_ADDR_LEN6) != 0) { | |||
2494 | memcpy(&ea.ether_addr_octet, bssid.i_bssid, | |||
2495 | sizeof(ea.ether_addr_octet)); | |||
2496 | printf(" bssid %s", ether_ntoa(&ea)); | |||
2497 | ||||
2498 | bzero(&nr, sizeof(nr)); | |||
2499 | bcopy(bssid.i_bssid, &nr.nr_macaddr, sizeof(nr.nr_macaddr)); | |||
2500 | strlcpy(nr.nr_ifname, ifname, sizeof(nr.nr_ifname)); | |||
2501 | if (ioctl(sock, SIOCG80211NODE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_nodereq) & 0x1fff) << 16) | ((('i' )) << 8) | ((211))), &nr) == 0) { | |||
2502 | if (nr.nr_max_rssi) | |||
2503 | printf(" %u%%", IEEE80211_NODEREQ_RSSI(&nr)((u_int)(((float)(&nr)->nr_rssi / (&nr)->nr_max_rssi ) * 100))); | |||
2504 | else | |||
2505 | printf(" %ddBm", nr.nr_rssi); | |||
2506 | assocfail = nr.nr_assoc_fail; | |||
2507 | } | |||
2508 | } | |||
2509 | ||||
2510 | if (inwkey == 0 && nwkey.i_wepon > IEEE80211_NWKEY_OPEN0) | |||
2511 | fputs(" nwkey", stdout(&__sF[1])); | |||
2512 | ||||
2513 | if (ipsk == 0 && psk.i_enabled) | |||
2514 | fputs(" wpakey", stdout(&__sF[1])); | |||
2515 | if (iwpa == 0 && wpa.i_enabled) { | |||
2516 | const char *sep; | |||
2517 | ||||
2518 | fputs(" wpaprotos ", stdout(&__sF[1])); sep = ""; | |||
2519 | if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA10x01) { | |||
2520 | fputs("wpa1", stdout(&__sF[1])); | |||
2521 | sep = ","; | |||
2522 | } | |||
2523 | if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA20x02) | |||
2524 | printf("%swpa2", sep); | |||
2525 | ||||
2526 | fputs(" wpaakms ", stdout(&__sF[1])); sep = ""; | |||
2527 | if (wpa.i_akms & IEEE80211_WPA_AKM_PSK0x01) { | |||
2528 | fputs("psk", stdout(&__sF[1])); | |||
2529 | sep = ","; | |||
2530 | } | |||
2531 | if (wpa.i_akms & IEEE80211_WPA_AKM_8021X0x02) | |||
2532 | printf("%s802.1x", sep); | |||
2533 | ||||
2534 | fputs(" wpaciphers ", stdout(&__sF[1])); | |||
2535 | print_cipherset(wpa.i_ciphers); | |||
2536 | ||||
2537 | fputs(" wpagroupcipher ", stdout(&__sF[1])); | |||
2538 | print_cipherset(wpa.i_groupcipher); | |||
2539 | } | |||
2540 | ||||
2541 | if (ipwr == 0 && power.i_enabled) | |||
2542 | printf(" powersave on (%dms sleep)", power.i_maxsleep); | |||
2543 | ||||
2544 | if (ioctl(sock, SIOCG80211FLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((216))), (caddr_t)&ifr) == 0 && | |||
2545 | ifr.ifr_flagsifr_ifru.ifru_flags) { | |||
2546 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
2547 | printb_status(ifr.ifr_flagsifr_ifru.ifru_flags, IEEE80211_F_USERBITS"\20\01HIDENWID\02NOBRIDGE\03STAYAUTH\04NOMIMO"); | |||
2548 | } | |||
2549 | ||||
2550 | if (assocfail) { | |||
2551 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
2552 | print_assoc_failures(assocfail); | |||
2553 | } | |||
2554 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
2555 | if (show_join) | |||
2556 | join_status(); | |||
2557 | if (shownet80211chans) | |||
2558 | ieee80211_listchans(); | |||
2559 | else if (shownet80211nodes) | |||
2560 | ieee80211_listnodes(); | |||
2561 | } | |||
2562 | ||||
2563 | void | |||
2564 | showjoin(const char *cmd, int val) | |||
2565 | { | |||
2566 | show_join = 1; | |||
2567 | return; | |||
2568 | } | |||
2569 | ||||
2570 | void | |||
2571 | join_status(void) | |||
2572 | { | |||
2573 | struct ieee80211_joinreq_all ja; | |||
2574 | struct ieee80211_join *jn = NULL((void *)0); | |||
2575 | struct ieee80211_wpaparams *wpa; | |||
2576 | int jsz = 100; | |||
2577 | int ojsz; | |||
2578 | int i; | |||
2579 | int r; | |||
2580 | int maxlen, len; | |||
2581 | ||||
2582 | bzero(&ja, sizeof(ja)); | |||
2583 | jn = recallocarray(NULL((void *)0), 0, jsz, sizeof(*jn)); | |||
2584 | if (jn == NULL((void *)0)) | |||
2585 | err(1, "recallocarray"); | |||
2586 | ojsz = jsz; | |||
2587 | while (1) { | |||
2588 | ja.ja_node = jn; | |||
2589 | ja.ja_size = jsz * sizeof(*jn); | |||
2590 | strlcpy(ja.ja_ifname, ifname, sizeof(ja.ja_ifname)); | |||
2591 | ||||
2592 | if ((r = ioctl(sock, SIOCG80211JOINALL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_joinreq_all) & 0x1fff) << 16) | ( (('i')) << 8) | ((218))), &ja)) != 0) { | |||
2593 | if (errno(*__errno()) == E2BIG7) { | |||
2594 | jsz += 100; | |||
2595 | jn = recallocarray(jn, ojsz, jsz, sizeof(*jn)); | |||
2596 | if (jn == NULL((void *)0)) | |||
2597 | err(1, "recallocarray"); | |||
2598 | ojsz = jsz; | |||
2599 | continue; | |||
2600 | } else if (errno(*__errno()) != ENOENT2) | |||
2601 | warn("%s: SIOCG80211JOINALL", ja.ja_ifname); | |||
2602 | return; | |||
2603 | } | |||
2604 | break; | |||
2605 | } | |||
2606 | ||||
2607 | if (!ja.ja_nodes) | |||
2608 | return; | |||
2609 | ||||
2610 | maxlen = 0; | |||
2611 | for (i = 0; i < ja.ja_nodes; i++) { | |||
2612 | len = len_string(jn[i].i_nwid, jn[i].i_len); | |||
2613 | if (len > maxlen) | |||
2614 | maxlen = len; | |||
2615 | } | |||
2616 | ||||
2617 | for (i = 0; i < ja.ja_nodes; i++) { | |||
2618 | printf("\t "); | |||
2619 | if (jn[i].i_len > IEEE80211_NWID_LEN32) | |||
2620 | jn[i].i_len = IEEE80211_NWID_LEN32; | |||
2621 | len = print_string(jn[i].i_nwid, jn[i].i_len); | |||
2622 | printf("%-*s", maxlen - len, ""); | |||
2623 | if (jn[i].i_flags) { | |||
2624 | const char *sep; | |||
2625 | printf(" "); | |||
2626 | ||||
2627 | if (jn[i].i_flags & IEEE80211_JOIN_NWKEY0x08) | |||
2628 | printf("nwkey"); | |||
2629 | ||||
2630 | if (jn[i].i_flags & IEEE80211_JOIN_WPA0x10) { | |||
2631 | wpa = &jn[i].i_wpaparams; | |||
2632 | ||||
2633 | printf("wpaprotos "); sep = ""; | |||
2634 | if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA10x01) { | |||
2635 | printf("wpa1"); | |||
2636 | sep = ","; | |||
2637 | } | |||
2638 | if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA20x02) | |||
2639 | printf("%swpa2", sep); | |||
2640 | ||||
2641 | printf(" wpaakms "); sep = ""; | |||
2642 | if (wpa->i_akms & IEEE80211_WPA_AKM_PSK0x01) { | |||
2643 | printf("psk"); | |||
2644 | sep = ","; | |||
2645 | } | |||
2646 | if (wpa->i_akms & IEEE80211_WPA_AKM_8021X0x02) | |||
2647 | printf("%s802.1x", sep); | |||
2648 | ||||
2649 | printf(" wpaciphers "); | |||
2650 | print_cipherset(wpa->i_ciphers); | |||
2651 | ||||
2652 | printf(" wpagroupcipher "); | |||
2653 | print_cipherset(wpa->i_groupcipher); | |||
2654 | } | |||
2655 | } | |||
2656 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
2657 | } | |||
2658 | } | |||
2659 | ||||
2660 | void | |||
2661 | ieee80211_listchans(void) | |||
2662 | { | |||
2663 | static struct ieee80211_chaninfo chans[256]; | |||
2664 | struct ieee80211_chanreq_all ca; | |||
2665 | int i; | |||
2666 | ||||
2667 | bzero(&ca, sizeof(ca)); | |||
2668 | bzero(chans, sizeof(chans)); | |||
2669 | ca.i_chans = chans; | |||
2670 | strlcpy(ca.i_name, ifname, sizeof(ca.i_name)); | |||
2671 | ||||
2672 | if (ioctl(sock, SIOCG80211ALLCHANS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_chanreq_all) & 0x1fff) << 16) | ( (('i')) << 8) | ((215))), &ca) != 0) { | |||
2673 | warn("%s: SIOCG80211ALLCHANS", ca.i_name); | |||
2674 | return; | |||
2675 | } | |||
2676 | printf("\t\t%4s %-8s %s\n", "chan", "freq", "properties"); | |||
2677 | for (i = 1; i < nitems(chans)(sizeof((chans)) / sizeof((chans)[0])); i++) { | |||
2678 | if (chans[i].ic_freq == 0) | |||
2679 | continue; | |||
2680 | printf("\t\t%4d %4d MHz ", i, chans[i].ic_freq); | |||
2681 | if (chans[i].ic_flags & IEEE80211_CHANINFO_PASSIVE0x0200) | |||
2682 | printf("passive scan"); | |||
2683 | else | |||
2684 | putchar('-')(!__isthreaded ? __sputc('-', (&__sF[1])) : (putc)('-', ( &__sF[1]))); | |||
2685 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
2686 | } | |||
2687 | } | |||
2688 | ||||
2689 | /* | |||
2690 | * Returns an integer less than, equal to, or greater than zero if nr1's | |||
2691 | * RSSI is respectively greater than, equal to, or less than nr2's RSSI. | |||
2692 | */ | |||
2693 | static int | |||
2694 | rssicmp(const void *nr1, const void *nr2) | |||
2695 | { | |||
2696 | const struct ieee80211_nodereq *x = nr1, *y = nr2; | |||
2697 | return y->nr_rssi < x->nr_rssi ? -1 : y->nr_rssi > x->nr_rssi; | |||
2698 | } | |||
2699 | ||||
2700 | void | |||
2701 | ieee80211_listnodes(void) | |||
2702 | { | |||
2703 | struct ieee80211_nodereq_all na; | |||
2704 | struct ieee80211_nodereq nr[512]; | |||
2705 | struct ifreq ifr; | |||
2706 | int i; | |||
2707 | ||||
2708 | if ((flags & IFF_UP0x1) == 0) { | |||
2709 | printf("\t\tcannot scan, interface is down\n"); | |||
2710 | return; | |||
2711 | } | |||
2712 | ||||
2713 | bzero(&ifr, sizeof(ifr)); | |||
2714 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
2715 | ||||
2716 | if (ioctl(sock, SIOCS80211SCAN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((210))), (caddr_t)&ifr) != 0) { | |||
2717 | if (errno(*__errno()) == EPERM1) | |||
2718 | printf("\t\tno permission to scan\n"); | |||
2719 | return; | |||
2720 | } | |||
2721 | ||||
2722 | bzero(&na, sizeof(na)); | |||
2723 | bzero(&nr, sizeof(nr)); | |||
2724 | na.na_node = nr; | |||
2725 | na.na_size = sizeof(nr); | |||
2726 | strlcpy(na.na_ifname, ifname, sizeof(na.na_ifname)); | |||
2727 | ||||
2728 | if (ioctl(sock, SIOCG80211ALLNODES(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ieee80211_nodereq_all) & 0x1fff) << 16) | ( (('i')) << 8) | ((214))), &na) != 0) { | |||
2729 | warn("%s: SIOCG80211ALLNODES", na.na_ifname); | |||
2730 | return; | |||
2731 | } | |||
2732 | ||||
2733 | if (!na.na_nodes) | |||
2734 | printf("\t\tnone\n"); | |||
2735 | else | |||
2736 | qsort(nr, na.na_nodes, sizeof(*nr), rssicmp); | |||
2737 | ||||
2738 | for (i = 0; i < na.na_nodes; i++) { | |||
2739 | printf("\t\t"); | |||
2740 | ieee80211_printnode(&nr[i]); | |||
2741 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
2742 | } | |||
2743 | } | |||
2744 | ||||
2745 | void | |||
2746 | ieee80211_printnode(struct ieee80211_nodereq *nr) | |||
2747 | { | |||
2748 | int len, i; | |||
2749 | ||||
2750 | if (nr->nr_flags & IEEE80211_NODEREQ_AP0x01 || | |||
2751 | nr->nr_capinfo & IEEE80211_CAPINFO_IBSS0x0002) { | |||
2752 | len = nr->nr_nwid_len; | |||
2753 | if (len > IEEE80211_NWID_LEN32) | |||
2754 | len = IEEE80211_NWID_LEN32; | |||
2755 | printf("nwid "); | |||
2756 | print_string(nr->nr_nwid, len); | |||
2757 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
2758 | ||||
2759 | printf("chan %u ", nr->nr_channel); | |||
2760 | ||||
2761 | printf("bssid %s ", | |||
2762 | ether_ntoa((struct ether_addr*)nr->nr_bssid)); | |||
2763 | } | |||
2764 | ||||
2765 | if ((nr->nr_flags & IEEE80211_NODEREQ_AP0x01) == 0) | |||
2766 | printf("lladdr %s ", | |||
2767 | ether_ntoa((struct ether_addr*)nr->nr_macaddr)); | |||
2768 | ||||
2769 | if (nr->nr_max_rssi) | |||
2770 | printf("%u%% ", IEEE80211_NODEREQ_RSSI(nr)((u_int)(((float)(nr)->nr_rssi / (nr)->nr_max_rssi) * 100 ))); | |||
2771 | else | |||
2772 | printf("%ddBm ", nr->nr_rssi); | |||
2773 | ||||
2774 | if (nr->nr_pwrsave) | |||
2775 | printf("powersave "); | |||
2776 | /* | |||
2777 | * Print our current Tx rate for associated nodes. | |||
2778 | * Print the fastest supported rate for APs. | |||
2779 | */ | |||
2780 | if ((nr->nr_flags & (IEEE80211_NODEREQ_AP0x01)) == 0) { | |||
2781 | if (nr->nr_flags & IEEE80211_NODEREQ_VHT0x10) { | |||
2782 | printf("VHT-MCS%d/%dSS", nr->nr_txmcs, nr->nr_vht_ss); | |||
2783 | } else if (nr->nr_flags & IEEE80211_NODEREQ_HT0x08) { | |||
2784 | printf("HT-MCS%d ", nr->nr_txmcs); | |||
2785 | } else if (nr->nr_nrates) { | |||
2786 | printf("%uM ", | |||
2787 | (nr->nr_rates[nr->nr_txrate] & IEEE80211_RATE_VAL0x7f) | |||
2788 | / 2); | |||
2789 | } | |||
2790 | } else if (nr->nr_max_rxrate) { | |||
2791 | printf("%uM HT ", nr->nr_max_rxrate); | |||
2792 | } else if (nr->nr_rxmcs[0] != 0) { | |||
2793 | for (i = IEEE80211_HT_NUM_MCS77 - 1; i >= 0; i--) { | |||
2794 | if (nr->nr_rxmcs[i / 8] & (1 << (i / 10))) | |||
2795 | break; | |||
2796 | } | |||
2797 | printf("HT-MCS%d ", i); | |||
2798 | } else if (nr->nr_nrates) { | |||
2799 | printf("%uM ", | |||
2800 | (nr->nr_rates[nr->nr_nrates - 1] & IEEE80211_RATE_VAL0x7f) / 2); | |||
2801 | } | |||
2802 | /* ESS is the default, skip it */ | |||
2803 | nr->nr_capinfo &= ~IEEE80211_CAPINFO_ESS0x0001; | |||
2804 | if (nr->nr_capinfo) { | |||
2805 | printb_status(nr->nr_capinfo, IEEE80211_CAPINFO_BITS"\10\01ESS\02IBSS\03CF_POLLABLE\04CF_POLLREQ" "\05PRIVACY\06SHORT_PREAMBLE\07PBCC\10CHNL_AGILITY" "\11SPECTRUM_MGMT\12QOS\13SHORT_SLOTTIME\14APSD" "\15RADIO_MEASUREMENT\16DSSSOFDM\17DELAYED_B_ACK\20IMMEDIATE_B_ACK"); | |||
2806 | if (nr->nr_capinfo & IEEE80211_CAPINFO_PRIVACY0x0010) { | |||
2807 | if (nr->nr_rsnprotos) { | |||
2808 | if (nr->nr_rsnprotos & IEEE80211_WPA_PROTO_WPA20x02) | |||
2809 | fputs(",wpa2", stdout(&__sF[1])); | |||
2810 | if (nr->nr_rsnprotos & IEEE80211_WPA_PROTO_WPA10x01) | |||
2811 | fputs(",wpa1", stdout(&__sF[1])); | |||
2812 | } else | |||
2813 | fputs(",wep", stdout(&__sF[1])); | |||
2814 | ||||
2815 | if (nr->nr_rsnakms & IEEE80211_WPA_AKM_8021X0x02 || | |||
2816 | nr->nr_rsnakms & IEEE80211_WPA_AKM_SHA256_8021X0x08) | |||
2817 | fputs(",802.1x", stdout(&__sF[1])); | |||
2818 | } | |||
2819 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
2820 | } | |||
2821 | ||||
2822 | if ((nr->nr_flags & IEEE80211_NODEREQ_AP0x01) == 0) | |||
2823 | printb_status(IEEE80211_NODEREQ_STATE(nr->nr_state)(1 << nr->nr_state), | |||
2824 | IEEE80211_NODEREQ_STATE_BITS"\20\01CACHE\02BSS\03AUTH\04ASSOC\05COLLECT"); | |||
2825 | else if (nr->nr_assoc_fail) | |||
2826 | print_assoc_failures(nr->nr_assoc_fail); | |||
2827 | } | |||
2828 | ||||
2829 | void | |||
2830 | init_current_media(void) | |||
2831 | { | |||
2832 | struct ifmediareq ifmr; | |||
2833 | ||||
2834 | /* | |||
2835 | * If we have not yet done so, grab the currently-selected | |||
2836 | * media. | |||
2837 | */ | |||
2838 | if ((actions & (A_MEDIA0x0001|A_MEDIAOPT(0x0002|0x0004)|A_MEDIAMODE0x0010)) == 0) { | |||
2839 | (void) memset(&ifmr, 0, sizeof(ifmr)); | |||
2840 | (void) strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); | |||
2841 | ||||
2842 | if (ioctl(sock, SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifmediareq) & 0x1fff) << 16) | ((('i')) << 8) | ((56))), (caddr_t)&ifmr) == -1) { | |||
2843 | /* | |||
2844 | * If we get E2BIG, the kernel is telling us | |||
2845 | * that there are more, so we can ignore it. | |||
2846 | */ | |||
2847 | if (errno(*__errno()) != E2BIG7) | |||
2848 | err(1, "%s: SIOCGIFMEDIA", ifmr.ifm_name); | |||
2849 | } | |||
2850 | ||||
2851 | media_current = ifmr.ifm_current; | |||
2852 | } | |||
2853 | ||||
2854 | /* Sanity. */ | |||
2855 | if (IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL) == 0) | |||
2856 | errx(1, "%s: no link type?", ifname); | |||
2857 | } | |||
2858 | ||||
2859 | void | |||
2860 | process_media_commands(void) | |||
2861 | { | |||
2862 | ||||
2863 | if ((actions & (A_MEDIA0x0001|A_MEDIAOPT(0x0002|0x0004)|A_MEDIAMODE0x0010)) == 0) { | |||
2864 | /* Nothing to do. */ | |||
2865 | return; | |||
2866 | } | |||
2867 | ||||
2868 | /* | |||
2869 | * Media already set up, and commands sanity-checked. Set/clear | |||
2870 | * any options, and we're ready to go. | |||
2871 | */ | |||
2872 | media_current |= mediaopt_set; | |||
2873 | media_current &= ~mediaopt_clear; | |||
2874 | ||||
2875 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
2876 | ifr.ifr_mediaifr_ifru.ifru_media = media_current; | |||
2877 | ||||
2878 | if (ioctl(sock, SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((55))), (caddr_t)&ifr) == -1) | |||
2879 | err(1, "%s: SIOCSIFMEDIA", ifr.ifr_name); | |||
2880 | } | |||
2881 | ||||
2882 | void | |||
2883 | setmedia(const char *val, int d) | |||
2884 | { | |||
2885 | uint64_t type, subtype, inst; | |||
2886 | ||||
2887 | if (val == NULL((void *)0)) { | |||
2888 | if (showmediaflag) | |||
2889 | usage(); | |||
2890 | showmediaflag = 1; | |||
2891 | return; | |||
2892 | } | |||
2893 | ||||
2894 | init_current_media(); | |||
2895 | ||||
2896 | /* Only one media command may be given. */ | |||
2897 | if (actions & A_MEDIA0x0001) | |||
2898 | errx(1, "only one `media' command may be issued"); | |||
2899 | ||||
2900 | /* Must not come after mode commands */ | |||
2901 | if (actions & A_MEDIAMODE0x0010) | |||
2902 | errx(1, "may not issue `media' after `mode' commands"); | |||
2903 | ||||
2904 | /* Must not come after mediaopt commands */ | |||
2905 | if (actions & A_MEDIAOPT(0x0002|0x0004)) | |||
2906 | errx(1, "may not issue `media' after `mediaopt' commands"); | |||
2907 | ||||
2908 | /* | |||
2909 | * No need to check if `instance' has been issued; setmediainst() | |||
2910 | * craps out if `media' has not been specified. | |||
2911 | */ | |||
2912 | ||||
2913 | type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL); | |||
2914 | inst = IFM_INST(media_current)(((media_current) & 0xff00000000000000ULL) >> 56); | |||
2915 | ||||
2916 | /* Look up the subtype. */ | |||
2917 | subtype = get_media_subtype(type, val); | |||
2918 | ||||
2919 | /* Build the new current media word. */ | |||
2920 | media_current = IFM_MAKEWORD(type, subtype, 0, inst)((type) | (subtype) | (0) | ((uint64_t)(inst) << 56)); | |||
2921 | ||||
2922 | /* Media will be set after other processing is complete. */ | |||
2923 | } | |||
2924 | ||||
2925 | void | |||
2926 | setmediamode(const char *val, int d) | |||
2927 | { | |||
2928 | uint64_t type, subtype, options, inst, mode; | |||
2929 | ||||
2930 | init_current_media(); | |||
2931 | ||||
2932 | /* Can only issue `mode' once. */ | |||
2933 | if (actions & A_MEDIAMODE0x0010) | |||
2934 | errx(1, "only one `mode' command may be issued"); | |||
2935 | ||||
2936 | type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL); | |||
2937 | subtype = IFM_SUBTYPE(media_current)((media_current) & 0x00000000000000ffULL); | |||
2938 | options = IFM_OPTIONS(media_current)((media_current) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL )); | |||
2939 | inst = IFM_INST(media_current)(((media_current) & 0xff00000000000000ULL) >> 56); | |||
2940 | ||||
2941 | if ((mode = get_media_mode(type, val)) == -1) | |||
2942 | errx(1, "invalid media mode: %s", val); | |||
2943 | media_current = IFM_MAKEWORD(type, subtype, options, inst)((type) | (subtype) | (options) | ((uint64_t)(inst) << 56 )) | mode; | |||
2944 | /* Media will be set after other processing is complete. */ | |||
2945 | } | |||
2946 | ||||
2947 | void | |||
2948 | unsetmediamode(const char *val, int d) | |||
2949 | { | |||
2950 | uint64_t type, subtype, options, inst; | |||
2951 | ||||
2952 | init_current_media(); | |||
2953 | ||||
2954 | /* Can only issue `mode' once. */ | |||
2955 | if (actions & A_MEDIAMODE0x0010) | |||
2956 | errx(1, "only one `mode' command may be issued"); | |||
2957 | ||||
2958 | type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL); | |||
2959 | subtype = IFM_SUBTYPE(media_current)((media_current) & 0x00000000000000ffULL); | |||
2960 | options = IFM_OPTIONS(media_current)((media_current) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL )); | |||
2961 | inst = IFM_INST(media_current)(((media_current) & 0xff00000000000000ULL) >> 56); | |||
2962 | ||||
2963 | media_current = IFM_MAKEWORD(type, subtype, options, inst)((type) | (subtype) | (options) | ((uint64_t)(inst) << 56 )) | | |||
2964 | (IFM_AUTO0ULL << IFM_MSHIFT32); | |||
2965 | /* Media will be set after other processing is complete. */ | |||
2966 | } | |||
2967 | ||||
2968 | void | |||
2969 | setmediaopt(const char *val, int d) | |||
2970 | { | |||
2971 | ||||
2972 | init_current_media(); | |||
2973 | ||||
2974 | /* Can only issue `mediaopt' once. */ | |||
2975 | if (actions & A_MEDIAOPTSET0x0002) | |||
2976 | errx(1, "only one `mediaopt' command may be issued"); | |||
2977 | ||||
2978 | /* Can't issue `mediaopt' if `instance' has already been issued. */ | |||
2979 | if (actions & A_MEDIAINST0x0008) | |||
2980 | errx(1, "may not issue `mediaopt' after `instance'"); | |||
2981 | ||||
2982 | mediaopt_set = get_media_options(IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL), val); | |||
2983 | ||||
2984 | /* Media will be set after other processing is complete. */ | |||
2985 | } | |||
2986 | ||||
2987 | void | |||
2988 | unsetmediaopt(const char *val, int d) | |||
2989 | { | |||
2990 | ||||
2991 | init_current_media(); | |||
2992 | ||||
2993 | /* Can only issue `-mediaopt' once. */ | |||
2994 | if (actions & A_MEDIAOPTCLR0x0004) | |||
2995 | errx(1, "only one `-mediaopt' command may be issued"); | |||
2996 | ||||
2997 | /* May not issue `media' and `-mediaopt'. */ | |||
2998 | if (actions & A_MEDIA0x0001) | |||
2999 | errx(1, "may not issue both `media' and `-mediaopt'"); | |||
3000 | ||||
3001 | /* | |||
3002 | * No need to check for A_MEDIAINST, since the test for A_MEDIA | |||
3003 | * implicitly checks for A_MEDIAINST. | |||
3004 | */ | |||
3005 | ||||
3006 | mediaopt_clear = get_media_options(IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL), val); | |||
3007 | ||||
3008 | /* Media will be set after other processing is complete. */ | |||
3009 | } | |||
3010 | ||||
3011 | void | |||
3012 | setmediainst(const char *val, int d) | |||
3013 | { | |||
3014 | uint64_t type, subtype, options, inst; | |||
3015 | const char *errmsg = NULL((void *)0); | |||
3016 | ||||
3017 | init_current_media(); | |||
3018 | ||||
3019 | /* Can only issue `instance' once. */ | |||
3020 | if (actions & A_MEDIAINST0x0008) | |||
3021 | errx(1, "only one `instance' command may be issued"); | |||
3022 | ||||
3023 | /* Must have already specified `media' */ | |||
3024 | if ((actions & A_MEDIA0x0001) == 0) | |||
3025 | errx(1, "must specify `media' before `instance'"); | |||
3026 | ||||
3027 | type = IFM_TYPE(media_current)((media_current) & 0x000000000000ff00ULL); | |||
3028 | subtype = IFM_SUBTYPE(media_current)((media_current) & 0x00000000000000ffULL); | |||
3029 | options = IFM_OPTIONS(media_current)((media_current) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL )); | |||
3030 | ||||
3031 | inst = strtonum(val, 0, IFM_INST_MAX(((0xff00000000000000ULL) & 0xff00000000000000ULL) >> 56), &errmsg); | |||
3032 | if (errmsg) | |||
3033 | errx(1, "media instance %s: %s", val, errmsg); | |||
3034 | ||||
3035 | media_current = IFM_MAKEWORD(type, subtype, options, inst)((type) | (subtype) | (options) | ((uint64_t)(inst) << 56 )); | |||
3036 | ||||
3037 | /* Media will be set after other processing is complete. */ | |||
3038 | } | |||
3039 | ||||
3040 | ||||
3041 | const struct ifmedia_description ifm_type_descriptions[] = | |||
3042 | IFM_TYPE_DESCRIPTIONS{ { 0x0000000000000100ULL, "Ethernet" }, { 0x0000000000000100ULL , "ether" }, { 0x0000000000000300ULL, "FDDI" }, { 0x0000000000000400ULL , "IEEE802.11" }, { 0x0000000000000500ULL, "TDM" }, { 0x0000000000000600ULL , "CARP" }, { 0, ((void *)0) }, }; | |||
3043 | ||||
3044 | const struct ifmedia_description ifm_subtype_descriptions[] = | |||
3045 | IFM_SUBTYPE_DESCRIPTIONS{ { 0ULL, "autoselect" }, { 0ULL, "auto" }, { 1ULL, "manual" } , { 2ULL, "none" }, { 0x0000000000000100ULL|3, "10baseT" }, { 0x0000000000000100ULL|3, "10baseT/UTP" }, { 0x0000000000000100ULL |3, "UTP" }, { 0x0000000000000100ULL|3, "10UTP" }, { 0x0000000000000100ULL |4, "10base2" }, { 0x0000000000000100ULL|4, "10base2/BNC" }, { 0x0000000000000100ULL|4, "BNC" }, { 0x0000000000000100ULL|4, "10BNC" }, { 0x0000000000000100ULL|5, "10base5" }, { 0x0000000000000100ULL |5, "10base5/AUI" }, { 0x0000000000000100ULL|5, "AUI" }, { 0x0000000000000100ULL |5, "10AUI" }, { 0x0000000000000100ULL|6, "100baseTX" }, { 0x0000000000000100ULL |6, "100TX" }, { 0x0000000000000100ULL|7, "100baseFX" }, { 0x0000000000000100ULL |7, "100FX" }, { 0x0000000000000100ULL|8, "100baseT4" }, { 0x0000000000000100ULL |8, "100T4" }, { 0x0000000000000100ULL|9, "100baseVG" }, { 0x0000000000000100ULL |9, "100VG" }, { 0x0000000000000100ULL|10, "100baseT2" }, { 0x0000000000000100ULL |10, "100T2" }, { 0x0000000000000100ULL|11, "1000baseSX" }, { 0x0000000000000100ULL|11, "1000SX" }, { 0x0000000000000100ULL |12, "10baseSTP" }, { 0x0000000000000100ULL|12, "STP" }, { 0x0000000000000100ULL |12, "10STP" }, { 0x0000000000000100ULL|13, "10baseFL" }, { 0x0000000000000100ULL |13, "FL" }, { 0x0000000000000100ULL|13, "10FL" }, { 0x0000000000000100ULL |14, "1000baseLX" }, { 0x0000000000000100ULL|14, "1000LX" }, { 0x0000000000000100ULL|15, "1000baseCX" }, { 0x0000000000000100ULL |15, "1000CX" }, { 0x0000000000000100ULL|16, "1000baseT" }, { 0x0000000000000100ULL|16, "1000T" }, { 0x0000000000000100ULL |16, "1000baseTX" }, { 0x0000000000000100ULL|16, "1000TX" }, { 0x0000000000000100ULL|17, "HomePNA1" }, { 0x0000000000000100ULL |17, "HPNA1" }, { 0x0000000000000100ULL|18, "10GbaseLR" }, { 0x0000000000000100ULL |18, "10GLR" }, { 0x0000000000000100ULL|18, "10GBASE-LR" }, { 0x0000000000000100ULL|19, "10GbaseSR" }, { 0x0000000000000100ULL |19, "10GSR" }, { 0x0000000000000100ULL|19, "10GBASE-SR" }, { 0x0000000000000100ULL|20, "10GbaseCX4" }, { 0x0000000000000100ULL |20, "10GCX4" }, { 0x0000000000000100ULL|20, "10GBASE-CX4" }, { 0x0000000000000100ULL|21, "2500baseSX" }, { 0x0000000000000100ULL |21, "2500SX" }, { 0x0000000000000100ULL|22, "10GbaseT" }, { 0x0000000000000100ULL |22, "10GT" }, { 0x0000000000000100ULL|22, "10GBASE-T" }, { 0x0000000000000100ULL |23, "10GSFP+Cu" }, { 0x0000000000000100ULL|23, "10GCu" }, { 0x0000000000000100ULL |24, "10GbaseLRM" }, { 0x0000000000000100ULL|24, "10GBASE-LRM" }, { 0x0000000000000100ULL|25, "40GbaseCR4" }, { 0x0000000000000100ULL |25, "40GBASE-CR4" }, { 0x0000000000000100ULL|26, "40GbaseSR4" }, { 0x0000000000000100ULL|26, "40GBASE-SR4" }, { 0x0000000000000100ULL |27, "40GbaseLR4" }, { 0x0000000000000100ULL|27, "40GBASE-LR4" }, { 0x0000000000000100ULL|28, "1000base-KX" }, { 0x0000000000000100ULL |28, "1000BASE-KX" }, { 0x0000000000000100ULL|29, "10GbaseKX4" }, { 0x0000000000000100ULL|29, "10GBASE-KX4" }, { 0x0000000000000100ULL |30, "10GbaseKR" }, { 0x0000000000000100ULL|30, "10GBASE-KR" } , { 0x0000000000000100ULL|31, "10GbaseCR1" }, { 0x0000000000000100ULL |31, "10GBASE-CR1" }, { 0x0000000000000100ULL|54, "10G-AOC" } , { 0x0000000000000100ULL|32, "20GbaseKR2" }, { 0x0000000000000100ULL |32, "20GBASE-KR2" }, { 0x0000000000000100ULL|33, "2500baseKX" }, { 0x0000000000000100ULL|33, "2500BASE-KX" }, { 0x0000000000000100ULL |34, "2500baseT" }, { 0x0000000000000100ULL|34, "2500BASE-T" } , { 0x0000000000000100ULL|35, "5000baseT" }, { 0x0000000000000100ULL |35, "5000BASE-T" }, { 0x0000000000000100ULL|36, "1000base-SGMII" }, { 0x0000000000000100ULL|36, "1000BASE-SGMII" }, { 0x0000000000000100ULL |37, "10GbaseSFI" }, { 0x0000000000000100ULL|37, "10GBASE-SFI" }, { 0x0000000000000100ULL|38, "40GbaseXLPPI" }, { 0x0000000000000100ULL |38, "40GBASE-XLPPI" }, { 0x0000000000000100ULL|39, "1000baseCX-SGMII" }, { 0x0000000000000100ULL|39, "1000BASE-CX-SGMII" }, { 0x0000000000000100ULL |40, "40GbaseKR4" }, { 0x0000000000000100ULL|40, "40GBASE-KR4" }, { 0x0000000000000100ULL|56, "40G-AOC" }, { 0x0000000000000100ULL |41, "10GbaseER" }, { 0x0000000000000100ULL|41, "10GBASE-ER" } , { 0x0000000000000100ULL|42, "100GbaseCR4" }, { 0x0000000000000100ULL |42, "100GBASE-CR4" }, { 0x0000000000000100ULL|43, "100GbaseSR4" }, { 0x0000000000000100ULL|43, "100GBASE-SR4" }, { 0x0000000000000100ULL |44, "100GbaseKR4" }, { 0x0000000000000100ULL|44, "100GBASE-KR4" }, { 0x0000000000000100ULL|45, "100GbaseLR4" }, { 0x0000000000000100ULL |45, "100GBASE-LR4" }, { 0x0000000000000100ULL|57, "100G-AOC" }, { 0x0000000000000100ULL|46, "56GbaseR4" }, { 0x0000000000000100ULL |46, "56GBASE-R4" }, { 0x0000000000000100ULL|47, "25GbaseCR" } , { 0x0000000000000100ULL|47, "25GBASE-CR" }, { 0x0000000000000100ULL |48, "25GbaseKR" }, { 0x0000000000000100ULL|48, "25GBASE-KR" } , { 0x0000000000000100ULL|49, "25GbaseSR" }, { 0x0000000000000100ULL |49, "25GBASE-SR" }, { 0x0000000000000100ULL|52, "25GbaseLR" } , { 0x0000000000000100ULL|52, "25GBASE-LR" }, { 0x0000000000000100ULL |53, "25GbaseER" }, { 0x0000000000000100ULL|53, "25GBASE-ER" } , { 0x0000000000000100ULL|55, "25G-AOC" }, { 0x0000000000000100ULL |50, "50GbaseCR2" }, { 0x0000000000000100ULL|50, "50GBASE-CR2" }, { 0x0000000000000100ULL|51, "50GbaseKR2" }, { 0x0000000000000100ULL |51, "50GBASE-KR2" }, { 0x0000000000000300ULL|3, "Single-mode" }, { 0x0000000000000300ULL|3, "SMF" }, { 0x0000000000000300ULL |4, "Multi-mode" }, { 0x0000000000000300ULL|4, "MMF" }, { 0x0000000000000300ULL |5, "UTP" }, { 0x0000000000000300ULL|5, "CDDI" }, { 0x0000000000000400ULL |3, "FH1" }, { 0x0000000000000400ULL|4, "FH2" }, { 0x0000000000000400ULL |5, "DS2" }, { 0x0000000000000400ULL|6, "DS5" }, { 0x0000000000000400ULL |7, "DS11" }, { 0x0000000000000400ULL|8, "DS1" }, { 0x0000000000000400ULL |9, "DS22" }, { 0x0000000000000400ULL|10, "OFDM6" }, { 0x0000000000000400ULL |11, "OFDM9" }, { 0x0000000000000400ULL|12, "OFDM12" }, { 0x0000000000000400ULL |13, "OFDM18" }, { 0x0000000000000400ULL|14, "OFDM24" }, { 0x0000000000000400ULL |15, "OFDM36" }, { 0x0000000000000400ULL|16, "OFDM48" }, { 0x0000000000000400ULL |17, "OFDM54" }, { 0x0000000000000400ULL|18, "OFDM72" }, { 0x0000000000000400ULL |19, "HT-MCS0" }, { 0x0000000000000400ULL|20, "HT-MCS1" }, { 0x0000000000000400ULL |21, "HT-MCS2" }, { 0x0000000000000400ULL|22, "HT-MCS3" }, { 0x0000000000000400ULL |23, "HT-MCS4" }, { 0x0000000000000400ULL|24, "HT-MCS5" }, { 0x0000000000000400ULL |25, "HT-MCS6" }, { 0x0000000000000400ULL|26, "HT-MCS7" }, { 0x0000000000000400ULL |27, "HT-MCS8" }, { 0x0000000000000400ULL|28, "HT-MCS9" }, { 0x0000000000000400ULL |29, "HT-MCS10" }, { 0x0000000000000400ULL|30, "HT-MCS11" }, { 0x0000000000000400ULL|31, "HT-MCS12" }, { 0x0000000000000400ULL |32, "HT-MCS13" }, { 0x0000000000000400ULL|33, "HT-MCS14" }, { 0x0000000000000400ULL|34, "HT-MCS15" }, { 0x0000000000000400ULL |35, "HT-MCS16" }, { 0x0000000000000400ULL|36, "HT-MCS17" }, { 0x0000000000000400ULL|37, "HT-MCS18" }, { 0x0000000000000400ULL |38, "HT-MCS19" }, { 0x0000000000000400ULL|39, "HT-MCS20" }, { 0x0000000000000400ULL|40, "HT-MCS21" }, { 0x0000000000000400ULL |41, "HT-MCS22" }, { 0x0000000000000400ULL|42, "HT-MCS23" }, { 0x0000000000000400ULL|43, "HT-MCS24" }, { 0x0000000000000400ULL |44, "HT-MCS25" }, { 0x0000000000000400ULL|45, "HT-MCS26" }, { 0x0000000000000400ULL|46, "HT-MCS27" }, { 0x0000000000000400ULL |47, "HT-MCS28" }, { 0x0000000000000400ULL|48, "HT-MCS29" }, { 0x0000000000000400ULL|49, "HT-MCS30" }, { 0x0000000000000400ULL |50, "HT-MCS31" }, { 0x0000000000000400ULL|51, "HT-MCS32" }, { 0x0000000000000400ULL|52, "HT-MCS33" }, { 0x0000000000000400ULL |53, "HT-MCS34" }, { 0x0000000000000400ULL|54, "HT-MCS35" }, { 0x0000000000000400ULL|55, "HT-MCS36" }, { 0x0000000000000400ULL |56, "HT-MCS37" }, { 0x0000000000000400ULL|57, "HT-MCS38" }, { 0x0000000000000400ULL|58, "HT-MCS39" }, { 0x0000000000000400ULL |59, "HT-MCS40" }, { 0x0000000000000400ULL|60, "HT-MCS41" }, { 0x0000000000000400ULL|61, "HT-MCS42" }, { 0x0000000000000400ULL |62, "HT-MCS43" }, { 0x0000000000000400ULL|63, "HT-MCS44" }, { 0x0000000000000400ULL|64, "HT-MCS45" }, { 0x0000000000000400ULL |65, "HT-MCS46" }, { 0x0000000000000400ULL|66, "HT-MCS47" }, { 0x0000000000000400ULL|67, "HT-MCS48" }, { 0x0000000000000400ULL |68, "HT-MCS49" }, { 0x0000000000000400ULL|69, "HT-MCS50" }, { 0x0000000000000400ULL|70, "HT-MCS51" }, { 0x0000000000000400ULL |71, "HT-MCS52" }, { 0x0000000000000400ULL|72, "HT-MCS53" }, { 0x0000000000000400ULL|73, "HT-MCS54" }, { 0x0000000000000400ULL |74, "HT-MCS55" }, { 0x0000000000000400ULL|75, "HT-MCS56" }, { 0x0000000000000400ULL|76, "HT-MCS57" }, { 0x0000000000000400ULL |77, "HT-MCS58" }, { 0x0000000000000400ULL|78, "HT-MCS59" }, { 0x0000000000000400ULL|79, "HT-MCS60" }, { 0x0000000000000400ULL |80, "HT-MCS61" }, { 0x0000000000000400ULL|81, "HT-MCS62" }, { 0x0000000000000400ULL|82, "HT-MCS63" }, { 0x0000000000000400ULL |83, "HT-MCS64" }, { 0x0000000000000400ULL|84, "HT-MCS65" }, { 0x0000000000000400ULL|85, "HT-MCS66" }, { 0x0000000000000400ULL |86, "HT-MCS67" }, { 0x0000000000000400ULL|87, "HT-MCS68" }, { 0x0000000000000400ULL|88, "HT-MCS69" }, { 0x0000000000000400ULL |89, "HT-MCS70" }, { 0x0000000000000400ULL|90, "HT-MCS71" }, { 0x0000000000000400ULL|91, "HT-MCS72" }, { 0x0000000000000400ULL |92, "HT-MCS73" }, { 0x0000000000000400ULL|93, "HT-MCS74" }, { 0x0000000000000400ULL|94, "HT-MCS75" }, { 0x0000000000000400ULL |95, "HT-MCS76" }, { 0x0000000000000400ULL|96, "VHT-MCS0" }, { 0x0000000000000400ULL|97, "VHT-MCS1" }, { 0x0000000000000400ULL |98, "VHT-MCS2" }, { 0x0000000000000400ULL|99, "VHT-MCS3" }, { 0x0000000000000400ULL|100, "VHT-MCS4" }, { 0x0000000000000400ULL |101, "VHT-MCS5" }, { 0x0000000000000400ULL|102, "VHT-MCS6" } , { 0x0000000000000400ULL|103, "VHT-MCS7" }, { 0x0000000000000400ULL |104, "VHT-MCS8" }, { 0x0000000000000400ULL|105, "VHT-MCS9" } , { 0x0000000000000500ULL|3, "t1" }, { 0x0000000000000500ULL| 4, "t1-ami" }, { 0x0000000000000500ULL|5, "e1" }, { 0x0000000000000500ULL |6, "e1-g.704" }, { 0x0000000000000500ULL|7, "e1-ami" }, { 0x0000000000000500ULL |8, "e1-ami-g.704" }, { 0x0000000000000500ULL|9, "t3" }, { 0x0000000000000500ULL |10, "t3-m13" }, { 0x0000000000000500ULL|11, "e3" }, { 0x0000000000000500ULL |12, "e3-g.751" }, { 0x0000000000000500ULL|13, "e3-g.832" }, { 0x0000000000000500ULL|14, "e1-g.704-crc4" }, { 0, ((void *)0 ) }, }; | |||
3046 | ||||
3047 | const struct ifmedia_description ifm_mode_descriptions[] = | |||
3048 | IFM_MODE_DESCRIPTIONS{ { 0ULL, "autoselect" }, { 0ULL, "auto" }, { 0x0000000000000400ULL |0x0000000100000000ULL, "11a" }, { 0x0000000000000400ULL|0x0000000200000000ULL , "11b" }, { 0x0000000000000400ULL|0x0000000300000000ULL, "11g" }, { 0x0000000000000400ULL|0x0000000400000000ULL, "fh" }, { 0x0000000000000400ULL |0x0000000800000000ULL, "11n" }, { 0x0000000000000400ULL|0x0000001000000000ULL , "11ac" }, { 0x0000000000000500ULL|0x0000000100000000ULL, "master" }, { 0, ((void *)0) }, }; | |||
3049 | ||||
3050 | const struct ifmedia_description ifm_option_descriptions[] = | |||
3051 | IFM_OPTION_DESCRIPTIONS{ { 0x0000010000000000ULL, "full-duplex" }, { 0x0000010000000000ULL , "fdx" }, { 0x0000020000000000ULL, "half-duplex" }, { 0x0000020000000000ULL , "hdx" }, { 0x0000100000000000ULL, "flag0" }, { 0x0000200000000000ULL , "flag1" }, { 0x0000400000000000ULL, "flag2" }, { 0x0000800000000000ULL , "loopback" }, { 0x0000800000000000ULL, "hw-loopback"}, { 0x0000800000000000ULL , "loop" }, { 0x0000000000000100ULL|0x0000000000010000ULL, "master" }, { 0x0000000000000100ULL|0x0000000000020000ULL, "rxpause" } , { 0x0000000000000100ULL|0x0000000000040000ULL, "txpause" }, { 0x0000000000000300ULL|0x00000100, "dual-attach" }, { 0x0000000000000300ULL |0x00000100, "das" }, { 0x0000000000000400ULL|0x0000000000010000ULL , "adhoc" }, { 0x0000000000000400ULL|0x0000000000020000ULL, "hostap" }, { 0x0000000000000400ULL|0x0000000000040000ULL, "ibss" }, { 0x0000000000000400ULL|0x0000000000080000ULL, "ibss-master" } , { 0x0000000000000400ULL|0x0000000000100000ULL, "monitor" }, { 0x0000000000000500ULL|0x0100, "hdlc-crc16" }, { 0x0000000000000500ULL |0x0200, "ppp" }, { 0x0000000000000500ULL|0x0400, "framerelay-ansi" }, { 0x0000000000000500ULL|0x0800, "framerelay-cisco" }, { 0x0000000000000500ULL |0x0400, "framerelay-itu" }, { 0, ((void *)0) }, }; | |||
3052 | ||||
3053 | const char * | |||
3054 | get_media_type_string(uint64_t mword) | |||
3055 | { | |||
3056 | const struct ifmedia_description *desc; | |||
3057 | ||||
3058 | for (desc = ifm_type_descriptions; desc->ifmt_string != NULL((void *)0); | |||
3059 | desc++) { | |||
3060 | if (IFM_TYPE(mword)((mword) & 0x000000000000ff00ULL) == desc->ifmt_word) | |||
3061 | return (desc->ifmt_string); | |||
3062 | } | |||
3063 | return ("<unknown type>"); | |||
3064 | } | |||
3065 | ||||
3066 | const char * | |||
3067 | get_media_subtype_string(uint64_t mword) | |||
3068 | { | |||
3069 | const struct ifmedia_description *desc; | |||
3070 | ||||
3071 | for (desc = ifm_subtype_descriptions; desc->ifmt_string != NULL((void *)0); | |||
3072 | desc++) { | |||
3073 | if (IFM_TYPE_MATCH(desc->ifmt_word, mword)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 || (((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((mword )) & 0x000000000000ff00ULL)) && | |||
3074 | IFM_SUBTYPE(desc->ifmt_word)((desc->ifmt_word) & 0x00000000000000ffULL) == IFM_SUBTYPE(mword)((mword) & 0x00000000000000ffULL)) | |||
3075 | return (desc->ifmt_string); | |||
3076 | } | |||
3077 | return ("<unknown subtype>"); | |||
3078 | } | |||
3079 | ||||
3080 | uint64_t | |||
3081 | get_media_subtype(uint64_t type, const char *val) | |||
3082 | { | |||
3083 | uint64_t rval; | |||
3084 | ||||
3085 | rval = lookup_media_word(ifm_subtype_descriptions, type, val); | |||
3086 | if (rval == -1) | |||
3087 | errx(1, "unknown %s media subtype: %s", | |||
3088 | get_media_type_string(type), val); | |||
3089 | ||||
3090 | return (rval); | |||
3091 | } | |||
3092 | ||||
3093 | uint64_t | |||
3094 | get_media_mode(uint64_t type, const char *val) | |||
3095 | { | |||
3096 | uint64_t rval; | |||
3097 | ||||
3098 | rval = lookup_media_word(ifm_mode_descriptions, type, val); | |||
3099 | if (rval == -1) | |||
3100 | errx(1, "unknown %s media mode: %s", | |||
3101 | get_media_type_string(type), val); | |||
3102 | return (rval); | |||
3103 | } | |||
3104 | ||||
3105 | uint64_t | |||
3106 | get_media_options(uint64_t type, const char *val) | |||
3107 | { | |||
3108 | char *optlist, *str; | |||
3109 | uint64_t option, rval = 0; | |||
3110 | ||||
3111 | /* We muck with the string, so copy it. */ | |||
3112 | optlist = strdup(val); | |||
3113 | if (optlist == NULL((void *)0)) | |||
3114 | err(1, "strdup"); | |||
3115 | str = optlist; | |||
3116 | ||||
3117 | /* | |||
3118 | * Look up the options in the user-provided comma-separated list. | |||
3119 | */ | |||
3120 | for (; (str = strtok(str, ",")) != NULL((void *)0); str = NULL((void *)0)) { | |||
3121 | option = lookup_media_word(ifm_option_descriptions, type, str); | |||
3122 | if (option == -1) | |||
3123 | errx(1, "unknown %s media option: %s", | |||
3124 | get_media_type_string(type), str); | |||
3125 | rval |= IFM_OPTIONS(option)((option) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL) ); | |||
3126 | } | |||
3127 | ||||
3128 | free(optlist); | |||
3129 | return (rval); | |||
3130 | } | |||
3131 | ||||
3132 | uint64_t | |||
3133 | lookup_media_word(const struct ifmedia_description *desc, uint64_t type, | |||
3134 | const char *val) | |||
3135 | { | |||
3136 | ||||
3137 | for (; desc->ifmt_string != NULL((void *)0); desc++) { | |||
3138 | if (IFM_TYPE_MATCH(desc->ifmt_word, type)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 || (((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((type )) & 0x000000000000ff00ULL)) && | |||
3139 | strcasecmp(desc->ifmt_string, val) == 0) | |||
3140 | return (desc->ifmt_word); | |||
3141 | } | |||
3142 | return (-1); | |||
3143 | } | |||
3144 | ||||
3145 | void | |||
3146 | print_media_word(uint64_t ifmw, int print_type, int as_syntax) | |||
3147 | { | |||
3148 | const struct ifmedia_description *desc; | |||
3149 | uint64_t seen_option = 0; | |||
3150 | ||||
3151 | if (print_type) | |||
3152 | printf("%s ", get_media_type_string(ifmw)); | |||
3153 | printf("%s%s", as_syntax ? "media " : "", | |||
3154 | get_media_subtype_string(ifmw)); | |||
3155 | ||||
3156 | /* Find mode. */ | |||
3157 | if (IFM_MODE(ifmw)((ifmw) & 0x000000ff00000000ULL) != 0) { | |||
3158 | for (desc = ifm_mode_descriptions; desc->ifmt_string != NULL((void *)0); | |||
3159 | desc++) { | |||
3160 | if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 || (((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((ifmw )) & 0x000000000000ff00ULL)) && | |||
3161 | IFM_MODE(ifmw)((ifmw) & 0x000000ff00000000ULL) == IFM_MODE(desc->ifmt_word)((desc->ifmt_word) & 0x000000ff00000000ULL)) { | |||
3162 | printf(" mode %s", desc->ifmt_string); | |||
3163 | break; | |||
3164 | } | |||
3165 | } | |||
3166 | } | |||
3167 | ||||
3168 | /* Find options. */ | |||
3169 | for (desc = ifm_option_descriptions; desc->ifmt_string != NULL((void *)0); | |||
3170 | desc++) { | |||
3171 | if (IFM_TYPE_MATCH(desc->ifmt_word, ifmw)((((desc->ifmt_word)) & 0x000000000000ff00ULL) == 0 || (((desc->ifmt_word)) & 0x000000000000ff00ULL) == (((ifmw )) & 0x000000000000ff00ULL)) && | |||
3172 | (IFM_OPTIONS(ifmw)((ifmw) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL)) & IFM_OPTIONS(desc->ifmt_word)((desc->ifmt_word) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL ))) != 0 && | |||
3173 | (seen_option & IFM_OPTIONS(desc->ifmt_word)((desc->ifmt_word) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL ))) == 0) { | |||
3174 | if (seen_option == 0) | |||
3175 | printf(" %s", as_syntax ? "mediaopt " : ""); | |||
3176 | printf("%s%s", seen_option ? "," : "", | |||
3177 | desc->ifmt_string); | |||
3178 | seen_option |= IFM_OPTIONS(desc->ifmt_word)((desc->ifmt_word) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL )); | |||
3179 | } | |||
3180 | } | |||
3181 | if (IFM_INST(ifmw)(((ifmw) & 0xff00000000000000ULL) >> 56) != 0) | |||
3182 | printf(" instance %lld", IFM_INST(ifmw)(((ifmw) & 0xff00000000000000ULL) >> 56)); | |||
3183 | } | |||
3184 | ||||
3185 | static void | |||
3186 | print_tunnel(const struct if_laddrreq *req) | |||
3187 | { | |||
3188 | char psrcaddr[NI_MAXHOST256]; | |||
3189 | char psrcport[NI_MAXSERV32]; | |||
3190 | char pdstaddr[NI_MAXHOST256]; | |||
3191 | char pdstport[NI_MAXSERV32]; | |||
3192 | const char *ver = ""; | |||
3193 | const int niflag = NI_NUMERICHOST1 | NI_NUMERICSERV2 | NI_DGRAM16; | |||
3194 | ||||
3195 | if (req == NULL((void *)0)) { | |||
3196 | printf("(unset)"); | |||
3197 | return; | |||
3198 | } | |||
3199 | ||||
3200 | psrcaddr[0] = pdstaddr[0] = '\0'; | |||
3201 | ||||
3202 | if (getnameinfo((struct sockaddr *)&req->addr, req->addr.ss_len, | |||
3203 | psrcaddr, sizeof(psrcaddr), psrcport, sizeof(psrcport), | |||
3204 | niflag) != 0) | |||
3205 | strlcpy(psrcaddr, "<error>", sizeof(psrcaddr)); | |||
3206 | if (req->addr.ss_family == AF_INET624) | |||
3207 | ver = "6"; | |||
3208 | ||||
3209 | printf("inet%s %s", ver, psrcaddr); | |||
3210 | if (strcmp(psrcport, "0") != 0) | |||
3211 | printf(":%s", psrcport); | |||
3212 | ||||
3213 | if (req->dstaddr.ss_family != AF_UNSPEC0) { | |||
3214 | in_port_t dstport = 0; | |||
3215 | const struct sockaddr_in *sin; | |||
3216 | const struct sockaddr_in6 *sin6; | |||
3217 | ||||
3218 | if (getnameinfo((struct sockaddr *)&req->dstaddr, | |||
3219 | req->dstaddr.ss_len, pdstaddr, sizeof(pdstaddr), | |||
3220 | pdstport, sizeof(pdstport), niflag) != 0) | |||
3221 | strlcpy(pdstaddr, "<error>", sizeof(pdstaddr)); | |||
3222 | ||||
3223 | printf(" --> %s", pdstaddr); | |||
3224 | if (strcmp(pdstport, "0") != 0) | |||
3225 | printf(":%s", pdstport); | |||
3226 | } | |||
3227 | } | |||
3228 | ||||
3229 | static void | |||
3230 | phys_status(int force) | |||
3231 | { | |||
3232 | struct if_laddrreq req; | |||
3233 | struct if_laddrreq *r = &req; | |||
3234 | ||||
3235 | memset(&req, 0, sizeof(req)); | |||
3236 | (void) strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)); | |||
3237 | if (ioctl(sock, SIOCGLIFPHYADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct if_laddrreq) & 0x1fff) << 16) | ((('i')) << 8) | ((75))), (caddr_t)&req) == -1) { | |||
3238 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
3239 | return; | |||
3240 | ||||
3241 | r = NULL((void *)0); | |||
3242 | } | |||
3243 | ||||
3244 | printf("\ttunnel: "); | |||
3245 | print_tunnel(r); | |||
3246 | ||||
3247 | if (ioctl(sock, SIOCGLIFPHYTTL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((169))), (caddr_t)&ifr) == 0) { | |||
3248 | if (ifr.ifr_ttlifr_ifru.ifru_metric == -1) | |||
3249 | printf(" ttl copy"); | |||
3250 | else if (ifr.ifr_ttlifr_ifru.ifru_metric > 0) | |||
3251 | printf(" ttl %d", ifr.ifr_ttlifr_ifru.ifru_metric); | |||
3252 | } | |||
3253 | ||||
3254 | if (ioctl(sock, SIOCGLIFPHYDF(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((194))), (caddr_t)&ifr) == 0) | |||
3255 | printf(" %s", ifr.ifr_dfifr_ifru.ifru_metric ? "df" : "nodf"); | |||
3256 | ||||
3257 | #ifndef SMALL | |||
3258 | if (ioctl(sock, SIOCGLIFPHYECN(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((200))), (caddr_t)&ifr) == 0) | |||
3259 | printf(" %s", ifr.ifr_metricifr_ifru.ifru_metric ? "ecn" : "noecn"); | |||
3260 | ||||
3261 | if (ioctl(sock, SIOCGLIFPHYRTABLE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((162))), (caddr_t)&ifr) == 0 && | |||
3262 | (rdomainid != 0 || ifr.ifr_rdomainidifr_ifru.ifru_metric != 0)) | |||
3263 | printf(" rdomain %d", ifr.ifr_rdomainidifr_ifru.ifru_metric); | |||
3264 | #endif | |||
3265 | printf("\n"); | |||
3266 | } | |||
3267 | ||||
3268 | #ifndef SMALL | |||
3269 | const uint64_t ifm_status_valid_list[] = IFM_STATUS_VALID_LIST{ 0x0000000000000001ULL, 0 }; | |||
3270 | ||||
3271 | const struct ifmedia_status_description ifm_status_descriptions[] = | |||
3272 | IFM_STATUS_DESCRIPTIONS{ { 0x0000000000000100ULL, 0x0000000000000001ULL, 0x0000000000000002ULL , { "no carrier", "active" } }, { 0x0000000000000300ULL, 0x0000000000000001ULL , 0x0000000000000002ULL, { "no ring", "inserted" } }, { 0x0000000000000400ULL , 0x0000000000000001ULL, 0x0000000000000002ULL, { "no network" , "active" } }, { 0x0000000000000500ULL, 0x0000000000000001ULL , 0x0000000000000002ULL, { "no carrier", "active" } }, { 0x0000000000000600ULL , 0x0000000000000001ULL, 0x0000000000000002ULL, { "backup", "master" } }, { 0, 0, 0, { ((void *)0), ((void *)0) } } }; | |||
3273 | #endif | |||
3274 | ||||
3275 | const struct if_status_description if_status_descriptions[] = | |||
3276 | LINK_STATE_DESCRIPTIONS{ { 0x06, 2, "no carrier" }, { 0x47, 2, "no network" }, { 0x17 , 2, "no carrier" }, { 0xf7, 2, "backup" }, { 0xf7, 4, "master" }, { 0xf7, 5, "master" }, { 0xf7, 6, "master" }, { 0, 4, "active" }, { 0, 5, "active" }, { 0, 6, "active" }, { 0, 0, "unknown" }, { 0, 1, "invalid" }, { 0, 2, "down" }, { 0, 3, "keepalive down" }, { 0, 0, ((void *)0) } }; | |||
3277 | ||||
3278 | const char * | |||
3279 | get_linkstate(int mt, int link_state) | |||
3280 | { | |||
3281 | const struct if_status_description *p; | |||
3282 | static char buf[8]; | |||
3283 | ||||
3284 | for (p = if_status_descriptions; p->ifs_string != NULL((void *)0); p++) { | |||
3285 | if (LINK_STATE_DESC_MATCH(p, mt, link_state)(((p)->ifs_type == (mt) || (p)->ifs_type == 0) && (p)->ifs_state == (link_state))) | |||
3286 | return (p->ifs_string); | |||
3287 | } | |||
3288 | snprintf(buf, sizeof(buf), "[#%d]", link_state); | |||
3289 | return buf; | |||
3290 | } | |||
3291 | ||||
3292 | /* | |||
3293 | * Print the status of the interface. If an address family was | |||
3294 | * specified, show it and it only; otherwise, show them all. | |||
3295 | */ | |||
3296 | void | |||
3297 | status(int link, struct sockaddr_dl *sdl, int ls, int ifaliases) | |||
3298 | { | |||
3299 | const struct afswtch *p = afp; | |||
3300 | struct ifmediareq ifmr; | |||
3301 | #ifndef SMALL | |||
3302 | struct ifreq ifrdesc; | |||
3303 | struct ifkalivereq ikardesc; | |||
3304 | char ifdescr[IFDESCRSIZE64]; | |||
3305 | char pifname[IF_NAMESIZE16]; | |||
3306 | #endif | |||
3307 | uint64_t *media_list; | |||
3308 | int i; | |||
3309 | char sep; | |||
3310 | ||||
3311 | ||||
3312 | printf("%s: ", ifname); | |||
3313 | printb("flags", flags | (xflags << 16), IFFBITS"\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6STATICARP" "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" "\15LINK0\16LINK1\17LINK2\20MULTICAST" "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII" "\30AUTOCONF4" "\31MONITOR" "\32LRO"); | |||
3314 | #ifndef SMALL | |||
3315 | if (rdomainid) | |||
3316 | printf(" rdomain %d", rdomainid); | |||
3317 | #endif | |||
3318 | if (metric) | |||
3319 | printf(" metric %lu", metric); | |||
3320 | if (mtu) | |||
3321 | printf(" mtu %lu", mtu); | |||
3322 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
3323 | #ifndef SMALL | |||
3324 | if (showcapsflag) | |||
3325 | printifhwfeatures(NULL((void *)0), 1); | |||
3326 | #endif | |||
3327 | if (sdl != NULL((void *)0) && sdl->sdl_alen && | |||
3328 | (sdl->sdl_type == IFT_ETHER0x06 || sdl->sdl_type == IFT_CARP0xf7)) | |||
3329 | (void)printf("\tlladdr %s\n", ether_ntoa( | |||
3330 | (struct ether_addr *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen)))); | |||
3331 | ||||
3332 | sep = '\t'; | |||
3333 | #ifndef SMALL | |||
3334 | (void) memset(&ifrdesc, 0, sizeof(ifrdesc)); | |||
3335 | (void) strlcpy(ifrdesc.ifr_name, ifname, sizeof(ifrdesc.ifr_name)); | |||
3336 | ifrdesc.ifr_dataifr_ifru.ifru_data = (caddr_t)&ifdescr; | |||
3337 | if (ioctl(sock, SIOCGIFDESCR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((129))), &ifrdesc) == 0 && | |||
3338 | strlen(ifrdesc.ifr_dataifr_ifru.ifru_data)) | |||
3339 | printf("\tdescription: %s\n", ifrdesc.ifr_dataifr_ifru.ifru_data); | |||
3340 | ||||
3341 | if (sdl != NULL((void *)0)) { | |||
3342 | printf("%cindex %u", sep, sdl->sdl_index); | |||
3343 | sep = ' '; | |||
3344 | } | |||
3345 | if (!is_bridge() && ioctl(sock, SIOCGIFPRIORITY(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((156))), &ifrdesc) == 0) { | |||
3346 | printf("%cpriority %d", sep, ifrdesc.ifr_metricifr_ifru.ifru_metric); | |||
3347 | sep = ' '; | |||
3348 | } | |||
3349 | #endif | |||
3350 | printf("%cllprio %d\n", sep, llprio); | |||
3351 | ||||
3352 | #ifndef SMALL | |||
3353 | (void) memset(&ikardesc, 0, sizeof(ikardesc)); | |||
3354 | (void) strlcpy(ikardesc.ikar_name, ifname, sizeof(ikardesc.ikar_name)); | |||
3355 | if (ioctl(sock, SIOCGETKALIVE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifkalivereq) & 0x1fff) << 16) | ((('i')) << 8) | ((164))), &ikardesc) == 0 && | |||
3356 | (ikardesc.ikar_timeo != 0 || ikardesc.ikar_cnt != 0)) | |||
3357 | printf("\tkeepalive: timeout %d count %d\n", | |||
3358 | ikardesc.ikar_timeo, ikardesc.ikar_cnt); | |||
3359 | if (ioctl(sock, SIOCGIFPAIR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((177))), &ifrdesc) == 0 && ifrdesc.ifr_indexifr_ifru.ifru_index != 0 && | |||
3360 | if_indextoname(ifrdesc.ifr_indexifr_ifru.ifru_index, pifname) != NULL((void *)0)) | |||
3361 | printf("\tpatch: %s\n", pifname); | |||
3362 | #endif | |||
3363 | getencap(); | |||
3364 | #ifndef SMALL | |||
3365 | carp_status(); | |||
3366 | pfsync_status(); | |||
3367 | pppoe_status(); | |||
3368 | sppp_status(); | |||
3369 | mpls_status(); | |||
3370 | pflow_status(); | |||
3371 | umb_status(); | |||
3372 | wg_status(ifaliases); | |||
3373 | #endif | |||
3374 | trunk_status(); | |||
3375 | getifgroups(); | |||
3376 | ||||
3377 | (void) memset(&ifmr, 0, sizeof(ifmr)); | |||
3378 | (void) strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); | |||
3379 | ||||
3380 | if (ioctl(sock, SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifmediareq) & 0x1fff) << 16) | ((('i')) << 8) | ((56))), (caddr_t)&ifmr) == -1) { | |||
3381 | /* | |||
3382 | * Interface doesn't support SIOC{G,S}IFMEDIA. | |||
3383 | */ | |||
3384 | if (ls != LINK_STATE_UNKNOWN0) | |||
3385 | printf("\tstatus: %s\n", | |||
3386 | get_linkstate(sdl->sdl_type, ls)); | |||
3387 | goto proto_status; | |||
3388 | } | |||
3389 | ||||
3390 | if (ifmr.ifm_count == 0) { | |||
3391 | warnx("%s: no media types?", ifname); | |||
3392 | goto proto_status; | |||
3393 | } | |||
3394 | ||||
3395 | media_list = calloc(ifmr.ifm_count, sizeof(*media_list)); | |||
3396 | if (media_list == NULL((void *)0)) | |||
3397 | err(1, "calloc"); | |||
3398 | ifmr.ifm_ulist = media_list; | |||
3399 | ||||
3400 | if (ioctl(sock, SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifmediareq) & 0x1fff) << 16) | ((('i')) << 8) | ((56))), (caddr_t)&ifmr) == -1) | |||
3401 | err(1, "%s: SIOCGIFMEDIA", ifmr.ifm_name); | |||
3402 | ||||
3403 | printf("\tmedia: "); | |||
3404 | print_media_word(ifmr.ifm_current, 1, 0); | |||
3405 | if (ifmr.ifm_active != ifmr.ifm_current) { | |||
3406 | putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', ( &__sF[1]))); | |||
3407 | putchar('(')(!__isthreaded ? __sputc('(', (&__sF[1])) : (putc)('(', ( &__sF[1]))); | |||
3408 | print_media_word(ifmr.ifm_active, 0, 0); | |||
3409 | putchar(')')(!__isthreaded ? __sputc(')', (&__sF[1])) : (putc)(')', ( &__sF[1]))); | |||
3410 | } | |||
3411 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
3412 | ||||
3413 | #ifdef SMALL | |||
3414 | printf("\tstatus: %s\n", get_linkstate(sdl->sdl_type, ls)); | |||
3415 | #else | |||
3416 | if (ifmr.ifm_status & IFM_AVALID0x0000000000000001ULL) { | |||
3417 | const struct ifmedia_status_description *ifms; | |||
3418 | int bitno, found = 0; | |||
3419 | ||||
3420 | printf("\tstatus: "); | |||
3421 | for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) { | |||
3422 | for (ifms = ifm_status_descriptions; | |||
3423 | ifms->ifms_valid != 0; ifms++) { | |||
3424 | if (ifms->ifms_type != | |||
3425 | IFM_TYPE(ifmr.ifm_current)((ifmr.ifm_current) & 0x000000000000ff00ULL) || | |||
3426 | ifms->ifms_valid != | |||
3427 | ifm_status_valid_list[bitno]) | |||
3428 | continue; | |||
3429 | printf("%s%s", found ? ", " : "", | |||
3430 | IFM_STATUS_DESC(ifms, ifmr.ifm_status)(ifms)->ifms_string[((ifms)->ifms_bit & (ifmr.ifm_status )) ? 1 : 0]); | |||
3431 | found = 1; | |||
3432 | ||||
3433 | /* | |||
3434 | * For each valid indicator bit, there's | |||
3435 | * only one entry for each media type, so | |||
3436 | * terminate the inner loop now. | |||
3437 | */ | |||
3438 | break; | |||
3439 | } | |||
3440 | } | |||
3441 | ||||
3442 | if (found == 0) | |||
3443 | printf("unknown"); | |||
3444 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
3445 | } | |||
3446 | ||||
3447 | if (showtransceiver) { | |||
3448 | if (if_sff_info(0) == -1) | |||
3449 | if (!aflag && errno(*__errno()) != EPERM1 && errno(*__errno()) != ENOTTY25) | |||
3450 | warn("%s transceiver", ifname); | |||
3451 | } | |||
3452 | #endif | |||
3453 | ieee80211_status(); | |||
3454 | ||||
3455 | if (showmediaflag) { | |||
3456 | uint64_t type; | |||
3457 | int printed_type = 0; | |||
3458 | ||||
3459 | for (type = IFM_NMIN0x0000000000000100ULL; type <= IFM_NMAX0x000000000000ff00ULL; type += IFM_NMIN0x0000000000000100ULL) { | |||
3460 | for (i = 0, printed_type = 0; i < ifmr.ifm_count; i++) { | |||
3461 | if (IFM_TYPE(media_list[i])((media_list[i]) & 0x000000000000ff00ULL) == type) { | |||
3462 | ||||
3463 | /* | |||
3464 | * Don't advertise media with fixed | |||
3465 | * data rates for wireless interfaces. | |||
3466 | * Normal people don't need these. | |||
3467 | */ | |||
3468 | if (type == IFM_IEEE802110x0000000000000400ULL && | |||
3469 | (media_list[i] & IFM_TMASK0x00000000000000ffULL) != | |||
3470 | IFM_AUTO0ULL) | |||
3471 | continue; | |||
3472 | ||||
3473 | if (printed_type == 0) { | |||
3474 | printf("\tsupported media:\n"); | |||
3475 | printed_type = 1; | |||
3476 | } | |||
3477 | printf("\t\t"); | |||
3478 | print_media_word(media_list[i], 0, 1); | |||
3479 | printf("\n"); | |||
3480 | } | |||
3481 | } | |||
3482 | } | |||
3483 | } | |||
3484 | ||||
3485 | free(media_list); | |||
3486 | ||||
3487 | proto_status: | |||
3488 | if (link == 0) { | |||
3489 | if ((p = afp) != NULL((void *)0)) { | |||
3490 | p->af_status(1); | |||
3491 | } else for (p = afs; p->af_name; p++) { | |||
3492 | ifr.ifr_addrifr_ifru.ifru_addr.sa_family = p->af_af; | |||
3493 | p->af_status(0); | |||
3494 | } | |||
3495 | } | |||
3496 | ||||
3497 | phys_status(0); | |||
3498 | #ifndef SMALL | |||
3499 | bridge_status(); | |||
3500 | #endif | |||
3501 | } | |||
3502 | ||||
3503 | void | |||
3504 | in_status(int force) | |||
3505 | { | |||
3506 | struct sockaddr_in *sin, sin2; | |||
3507 | ||||
3508 | getsock(AF_INET2); | |||
3509 | if (sock == -1) { | |||
3510 | if (errno(*__errno()) == EPROTONOSUPPORT43) | |||
3511 | return; | |||
3512 | err(1, "socket"); | |||
3513 | } | |||
3514 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3515 | sin = (struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr; | |||
3516 | ||||
3517 | /* | |||
3518 | * We keep the interface address and reset it before each | |||
3519 | * ioctl() so we can get ifaliases information (as opposed | |||
3520 | * to the primary interface netmask/dstaddr/broadaddr, if | |||
3521 | * the ifr_addr field is zero). | |||
3522 | */ | |||
3523 | memcpy(&sin2, &ifr.ifr_addrifr_ifru.ifru_addr, sizeof(sin2)); | |||
3524 | ||||
3525 | printf("\tinet %s", inet_ntoa(sin->sin_addr)); | |||
3526 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3527 | if (ioctl(sock, SIOCGIFNETMASK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((37))), (caddr_t)&ifr) == -1) { | |||
3528 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
3529 | warn("SIOCGIFNETMASK"); | |||
3530 | memset(&ifr.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr.ifr_addrifr_ifru.ifru_addr)); | |||
3531 | } else | |||
3532 | netmask.sin_addr = | |||
3533 | ((struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr)->sin_addr; | |||
3534 | if (flags & IFF_POINTOPOINT0x10) { | |||
3535 | memcpy(&ifr.ifr_addrifr_ifru.ifru_addr, &sin2, sizeof(sin2)); | |||
3536 | if (ioctl(sock, SIOCGIFDSTADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((34))), (caddr_t)&ifr) == -1) { | |||
3537 | if (errno(*__errno()) == EADDRNOTAVAIL49) | |||
3538 | memset(&ifr.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr.ifr_addrifr_ifru.ifru_addr)); | |||
3539 | else | |||
3540 | warn("SIOCGIFDSTADDR"); | |||
3541 | } | |||
3542 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3543 | sin = (struct sockaddr_in *)&ifr.ifr_dstaddrifr_ifru.ifru_dstaddr; | |||
3544 | printf(" --> %s", inet_ntoa(sin->sin_addr)); | |||
3545 | } | |||
3546 | printf(" netmask 0x%x", ntohl(netmask.sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(netmask.sin_addr.s_addr) ? ( __uint32_t)(((__uint32_t)(netmask.sin_addr.s_addr) & 0xff ) << 24 | ((__uint32_t)(netmask.sin_addr.s_addr) & 0xff00 ) << 8 | ((__uint32_t)(netmask.sin_addr.s_addr) & 0xff0000 ) >> 8 | ((__uint32_t)(netmask.sin_addr.s_addr) & 0xff000000 ) >> 24) : __swap32md(netmask.sin_addr.s_addr))); | |||
3547 | if (flags & IFF_BROADCAST0x2) { | |||
3548 | memcpy(&ifr.ifr_addrifr_ifru.ifru_addr, &sin2, sizeof(sin2)); | |||
3549 | if (ioctl(sock, SIOCGIFBRDADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((35))), (caddr_t)&ifr) == -1) { | |||
3550 | if (errno(*__errno()) == EADDRNOTAVAIL49) | |||
3551 | memset(&ifr.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr.ifr_addrifr_ifru.ifru_addr)); | |||
3552 | else | |||
3553 | warn("SIOCGIFBRDADDR"); | |||
3554 | } | |||
3555 | (void) strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3556 | sin = (struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr; | |||
3557 | if (sin->sin_addr.s_addr != 0) | |||
3558 | printf(" broadcast %s", inet_ntoa(sin->sin_addr)); | |||
3559 | } | |||
3560 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
3561 | } | |||
3562 | ||||
3563 | void | |||
3564 | setifprefixlen(const char *addr, int d) | |||
3565 | { | |||
3566 | if (afp->af_getprefix) | |||
3567 | afp->af_getprefix(addr, MASK2); | |||
3568 | explicit_prefix = 1; | |||
3569 | } | |||
3570 | ||||
3571 | void | |||
3572 | in6_fillscopeid(struct sockaddr_in6 *sin6) | |||
3573 | { | |||
3574 | #ifdef __KAME__ | |||
3575 | if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe ) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8 [1] & 0xc0) == 0x80)) && | |||
3576 | sin6->sin6_scope_id == 0) { | |||
3577 | sin6->sin6_scope_id = | |||
3578 | ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2])(__uint16_t)(__builtin_constant_p(*(u_int16_t *)&sin6-> sin6_addr.__u6_addr.__u6_addr8[2]) ? (__uint16_t)(((__uint16_t )(*(u_int16_t *)&sin6->sin6_addr.__u6_addr.__u6_addr8[ 2]) & 0xffU) << 8 | ((__uint16_t)(*(u_int16_t *)& sin6->sin6_addr.__u6_addr.__u6_addr8[2]) & 0xff00U) >> 8) : __swap16md(*(u_int16_t *)&sin6->sin6_addr.__u6_addr .__u6_addr8[2])); | |||
3579 | sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] = sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[3] = 0; | |||
3580 | } | |||
3581 | #endif /* __KAME__ */ | |||
3582 | } | |||
3583 | ||||
3584 | /* XXX not really an alias */ | |||
3585 | void | |||
3586 | in6_alias(struct in6_ifreq *creq) | |||
3587 | { | |||
3588 | struct sockaddr_in6 *sin6; | |||
3589 | struct in6_ifreq ifr6; /* shadows file static variable */ | |||
3590 | u_int32_t scopeid; | |||
3591 | char hbuf[NI_MAXHOST256]; | |||
3592 | const int niflag = NI_NUMERICHOST1; | |||
3593 | ||||
3594 | /* Get the non-alias address for this interface. */ | |||
3595 | getsock(AF_INET624); | |||
3596 | if (sock == -1) { | |||
3597 | if (errno(*__errno()) == EPROTONOSUPPORT43) | |||
3598 | return; | |||
3599 | err(1, "socket"); | |||
3600 | } | |||
3601 | ||||
3602 | sin6 = (struct sockaddr_in6 *)&creq->ifr_addrifr_ifru.ifru_addr; | |||
3603 | ||||
3604 | in6_fillscopeid(sin6); | |||
3605 | scopeid = sin6->sin6_scope_id; | |||
3606 | if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, | |||
3607 | hbuf, sizeof(hbuf), NULL((void *)0), 0, niflag) != 0) | |||
3608 | strlcpy(hbuf, "", sizeof hbuf); | |||
3609 | printf("\tinet6 %s", hbuf); | |||
3610 | ||||
3611 | if (flags & IFF_POINTOPOINT0x10) { | |||
3612 | (void) memset(&ifr6, 0, sizeof(ifr6)); | |||
3613 | (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); | |||
3614 | ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr; | |||
3615 | if (ioctl(sock, SIOCGIFDSTADDR_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((34))), (caddr_t)&ifr6) == -1) { | |||
3616 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
3617 | warn("SIOCGIFDSTADDR_IN6"); | |||
3618 | (void) memset(&ifr6.ifr_addrifr_ifru.ifru_addr, 0, sizeof(ifr6.ifr_addrifr_ifru.ifru_addr)); | |||
3619 | ifr6.ifr_addrifr_ifru.ifru_addr.sin6_family = AF_INET624; | |||
3620 | ifr6.ifr_addrifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6); | |||
3621 | } | |||
3622 | sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addrifr_ifru.ifru_addr; | |||
3623 | in6_fillscopeid(sin6); | |||
3624 | if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, | |||
3625 | hbuf, sizeof(hbuf), NULL((void *)0), 0, niflag) != 0) | |||
3626 | strlcpy(hbuf, "", sizeof hbuf); | |||
3627 | printf(" --> %s", hbuf); | |||
3628 | } | |||
3629 | ||||
3630 | (void) memset(&ifr6, 0, sizeof(ifr6)); | |||
3631 | (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); | |||
3632 | ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr; | |||
3633 | if (ioctl(sock, SIOCGIFNETMASK_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((37))), (caddr_t)&ifr6) == -1) { | |||
3634 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
3635 | warn("SIOCGIFNETMASK_IN6"); | |||
3636 | } else { | |||
3637 | sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addrifr_ifru.ifru_addr; | |||
3638 | printf(" prefixlen %d", prefix(&sin6->sin6_addr, | |||
3639 | sizeof(struct in6_addr))); | |||
3640 | } | |||
3641 | ||||
3642 | (void) memset(&ifr6, 0, sizeof(ifr6)); | |||
3643 | (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); | |||
3644 | ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr; | |||
3645 | if (ioctl(sock, SIOCGIFAFLAG_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((73))), (caddr_t)&ifr6) == -1) { | |||
3646 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
3647 | warn("SIOCGIFAFLAG_IN6"); | |||
3648 | } else { | |||
3649 | if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST0x01) | |||
3650 | printf(" anycast"); | |||
3651 | if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE0x02) | |||
3652 | printf(" tentative"); | |||
3653 | if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED0x04) | |||
3654 | printf(" duplicated"); | |||
3655 | if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED0x08) | |||
3656 | printf(" detached"); | |||
3657 | if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED0x10) | |||
3658 | printf(" deprecated"); | |||
3659 | if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_AUTOCONF0x40) | |||
3660 | printf(" autoconf"); | |||
3661 | if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY0x80) | |||
3662 | printf(" temporary"); | |||
3663 | } | |||
3664 | ||||
3665 | if (scopeid) | |||
3666 | printf(" scopeid 0x%x", scopeid); | |||
3667 | ||||
3668 | if (Lflag) { | |||
3669 | struct in6_addrlifetime *lifetime; | |||
3670 | ||||
3671 | (void) memset(&ifr6, 0, sizeof(ifr6)); | |||
3672 | (void) strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name)); | |||
3673 | ifr6.ifr_addrifr_ifru.ifru_addr = creq->ifr_addrifr_ifru.ifru_addr; | |||
3674 | lifetime = &ifr6.ifr_ifru.ifru_lifetime; | |||
3675 | if (ioctl(sock, SIOCGIFALIFETIME_IN6(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct in6_ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((81))), (caddr_t)&ifr6) == -1) { | |||
3676 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
3677 | warn("SIOCGIFALIFETIME_IN6"); | |||
3678 | } else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) { | |||
3679 | time_t t = time(NULL((void *)0)); | |||
3680 | ||||
3681 | printf(" pltime "); | |||
3682 | if (lifetime->ia6t_preferred) { | |||
3683 | printf("%s", lifetime->ia6t_preferred < t | |||
3684 | ? "0" : | |||
3685 | sec2str(lifetime->ia6t_preferred - t)); | |||
3686 | } else | |||
3687 | printf("infty"); | |||
3688 | ||||
3689 | printf(" vltime "); | |||
3690 | if (lifetime->ia6t_expire) { | |||
3691 | printf("%s", lifetime->ia6t_expire < t | |||
3692 | ? "0" | |||
3693 | : sec2str(lifetime->ia6t_expire - t)); | |||
3694 | } else | |||
3695 | printf("infty"); | |||
3696 | } | |||
3697 | } | |||
3698 | ||||
3699 | printf("\n"); | |||
3700 | } | |||
3701 | ||||
3702 | void | |||
3703 | in6_status(int force) | |||
3704 | { | |||
3705 | in6_alias((struct in6_ifreq *)&ifr6); | |||
3706 | } | |||
3707 | ||||
3708 | #ifndef SMALL | |||
3709 | void | |||
3710 | settunnel(const char *src, const char *dst) | |||
3711 | { | |||
3712 | char srcbuf[HOST_NAME_MAX255], dstbuf[HOST_NAME_MAX255]; | |||
3713 | const char *srcport, *dstport; | |||
3714 | const char *srcaddr, *dstaddr; | |||
3715 | struct addrinfo *srcres, *dstres; | |||
3716 | struct addrinfo hints = { | |||
3717 | .ai_family = AF_UNSPEC0, | |||
3718 | .ai_socktype = SOCK_DGRAM2, | |||
3719 | .ai_protocol = IPPROTO_UDP17, | |||
3720 | .ai_flags = AI_PASSIVE1, | |||
3721 | }; | |||
3722 | int ecode; | |||
3723 | size_t len; | |||
3724 | struct if_laddrreq req; | |||
3725 | ||||
3726 | srcport = strchr(src, ':'); | |||
3727 | if (srcport == NULL((void *)0) || srcport != strrchr(src, ':')) { | |||
3728 | /* no port or IPv6 */ | |||
3729 | srcaddr = src; | |||
3730 | srcport = NULL((void *)0); | |||
3731 | } else { | |||
3732 | len = srcport - src; | |||
3733 | if (len >= sizeof(srcbuf)) | |||
3734 | errx(1, "src %s bad value", src); | |||
3735 | memcpy(srcbuf, src, len); | |||
3736 | srcbuf[len] = '\0'; | |||
3737 | ||||
3738 | srcaddr = srcbuf; | |||
3739 | srcport++; | |||
3740 | } | |||
3741 | ||||
3742 | dstport = strchr(dst, ':'); | |||
3743 | if (dstport == NULL((void *)0) || dstport != strrchr(dst, ':')) { | |||
3744 | /* no port or IPv6 */ | |||
3745 | dstaddr = dst; | |||
3746 | dstport = NULL((void *)0); | |||
3747 | } else { | |||
3748 | len = dstport - dst; | |||
3749 | if (len >= sizeof(dstbuf)) | |||
3750 | errx(1, "dst %s bad value", dst); | |||
3751 | memcpy(dstbuf, dst, len); | |||
3752 | dstbuf[len] = '\0'; | |||
3753 | ||||
3754 | dstaddr = dstbuf; | |||
3755 | dstport++; | |||
3756 | } | |||
3757 | ||||
3758 | if ((ecode = getaddrinfo(srcaddr, srcport, &hints, &srcres)) != 0) | |||
3759 | errx(1, "error in parsing address string: %s", | |||
3760 | gai_strerror(ecode)); | |||
3761 | ||||
3762 | hints.ai_flags = 0; | |||
3763 | if ((ecode = getaddrinfo(dstaddr, dstport, &hints, &dstres)) != 0) | |||
3764 | errx(1, "error in parsing address string: %s", | |||
3765 | gai_strerror(ecode)); | |||
3766 | ||||
3767 | if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family) | |||
3768 | errx(1, | |||
3769 | "source and destination address families do not match"); | |||
3770 | ||||
3771 | memset(&req, 0, sizeof(req)); | |||
3772 | (void) strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)); | |||
3773 | memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); | |||
3774 | memcpy(&req.dstaddr, dstres->ai_addr, dstres->ai_addrlen); | |||
3775 | if (ioctl(sock, SIOCSLIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct if_laddrreq) & 0x1fff) << 16) | ((('i')) << 8) | ((74))), &req) == -1) | |||
3776 | warn("SIOCSLIFPHYADDR"); | |||
3777 | ||||
3778 | freeaddrinfo(srcres); | |||
3779 | freeaddrinfo(dstres); | |||
3780 | } | |||
3781 | ||||
3782 | void | |||
3783 | settunneladdr(const char *src, int ignored) | |||
3784 | { | |||
3785 | char srcbuf[HOST_NAME_MAX255]; | |||
3786 | const char *srcport; | |||
3787 | const char *srcaddr; | |||
3788 | struct addrinfo *srcres; | |||
3789 | struct addrinfo hints = { | |||
3790 | .ai_family = AF_UNSPEC0, | |||
3791 | .ai_socktype = SOCK_DGRAM2, | |||
3792 | .ai_protocol = IPPROTO_UDP17, | |||
3793 | .ai_flags = AI_PASSIVE1, | |||
3794 | }; | |||
3795 | struct if_laddrreq req; | |||
3796 | ssize_t len; | |||
3797 | int rv; | |||
3798 | ||||
3799 | srcport = strchr(src, ':'); | |||
3800 | if (srcport == NULL((void *)0) || srcport != strrchr(src, ':')) { | |||
3801 | /* no port or IPv6 */ | |||
3802 | srcaddr = src; | |||
3803 | srcport = NULL((void *)0); | |||
3804 | } else { | |||
3805 | len = srcport - src; | |||
3806 | if (len >= sizeof(srcbuf)) | |||
3807 | errx(1, "src %s bad value", src); | |||
3808 | memcpy(srcbuf, src, len); | |||
3809 | srcbuf[len] = '\0'; | |||
3810 | ||||
3811 | srcaddr = srcbuf; | |||
3812 | srcport++; | |||
3813 | } | |||
3814 | ||||
3815 | rv = getaddrinfo(srcaddr, srcport, &hints, &srcres); | |||
3816 | if (rv != 0) | |||
3817 | errx(1, "tunneladdr %s: %s", src, gai_strerror(rv)); | |||
3818 | ||||
3819 | memset(&req, 0, sizeof(req)); | |||
3820 | len = strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)); | |||
3821 | if (len >= sizeof(req.iflr_name)) | |||
3822 | errx(1, "%s: Interface name too long", ifname); | |||
3823 | ||||
3824 | memcpy(&req.addr, srcres->ai_addr, srcres->ai_addrlen); | |||
3825 | ||||
3826 | req.dstaddr.ss_len = 2; | |||
3827 | req.dstaddr.ss_family = AF_UNSPEC0; | |||
3828 | ||||
3829 | if (ioctl(sock, SIOCSLIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct if_laddrreq) & 0x1fff) << 16) | ((('i')) << 8) | ((74))), &req) == -1) | |||
3830 | warn("tunneladdr %s", src); | |||
3831 | ||||
3832 | freeaddrinfo(srcres); | |||
3833 | } | |||
3834 | ||||
3835 | void | |||
3836 | deletetunnel(const char *ignored, int alsoignored) | |||
3837 | { | |||
3838 | if (ioctl(sock, SIOCDIFPHYADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((73))), &ifr) == -1) | |||
3839 | warn("SIOCDIFPHYADDR"); | |||
3840 | } | |||
3841 | ||||
3842 | void | |||
3843 | settunnelinst(const char *id, int param) | |||
3844 | { | |||
3845 | const char *errmsg = NULL((void *)0); | |||
3846 | int rdomainid; | |||
3847 | ||||
3848 | rdomainid = strtonum(id, 0, RT_TABLEID_MAX255, &errmsg); | |||
3849 | if (errmsg) | |||
3850 | errx(1, "rdomain %s: %s", id, errmsg); | |||
3851 | ||||
3852 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3853 | ifr.ifr_rdomainidifr_ifru.ifru_metric = rdomainid; | |||
3854 | if (ioctl(sock, SIOCSLIFPHYRTABLE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((161))), (caddr_t)&ifr) == -1) | |||
3855 | warn("SIOCSLIFPHYRTABLE"); | |||
3856 | } | |||
3857 | ||||
3858 | void | |||
3859 | unsettunnelinst(const char *ignored, int alsoignored) | |||
3860 | { | |||
3861 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3862 | ifr.ifr_rdomainidifr_ifru.ifru_metric = 0; | |||
3863 | if (ioctl(sock, SIOCSLIFPHYRTABLE((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((161))), (caddr_t)&ifr) == -1) | |||
3864 | warn("SIOCSLIFPHYRTABLE"); | |||
3865 | } | |||
3866 | ||||
3867 | void | |||
3868 | settunnelttl(const char *id, int param) | |||
3869 | { | |||
3870 | const char *errmsg = NULL((void *)0); | |||
3871 | int ttl; | |||
3872 | ||||
3873 | if (strcmp(id, "copy") == 0) | |||
3874 | ttl = -1; | |||
3875 | else { | |||
3876 | ttl = strtonum(id, 0, 0xff, &errmsg); | |||
3877 | if (errmsg) | |||
3878 | errx(1, "tunnelttl %s: %s", id, errmsg); | |||
3879 | } | |||
3880 | ||||
3881 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3882 | ifr.ifr_ttlifr_ifru.ifru_metric = ttl; | |||
3883 | if (ioctl(sock, SIOCSLIFPHYTTL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((168))), (caddr_t)&ifr) == -1) | |||
3884 | warn("SIOCSLIFPHYTTL"); | |||
3885 | } | |||
3886 | ||||
3887 | void | |||
3888 | settunneldf(const char *ignored, int alsoignored) | |||
3889 | { | |||
3890 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3891 | ifr.ifr_dfifr_ifru.ifru_metric = 1; | |||
3892 | if (ioctl(sock, SIOCSLIFPHYDF((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((193))), (caddr_t)&ifr) == -1) | |||
3893 | warn("SIOCSLIFPHYDF"); | |||
3894 | } | |||
3895 | ||||
3896 | void | |||
3897 | settunnelnodf(const char *ignored, int alsoignored) | |||
3898 | { | |||
3899 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3900 | ifr.ifr_dfifr_ifru.ifru_metric = 0; | |||
3901 | if (ioctl(sock, SIOCSLIFPHYDF((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((193))), (caddr_t)&ifr) == -1) | |||
3902 | warn("SIOCSLIFPHYDF"); | |||
3903 | } | |||
3904 | ||||
3905 | void | |||
3906 | settunnelecn(const char *ignored, int alsoignored) | |||
3907 | { | |||
3908 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3909 | ifr.ifr_metricifr_ifru.ifru_metric = 1; | |||
3910 | if (ioctl(sock, SIOCSLIFPHYECN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((199))), (caddr_t)&ifr) == -1) | |||
3911 | warn("SIOCSLIFPHYECN"); | |||
3912 | } | |||
3913 | ||||
3914 | void | |||
3915 | settunnelnoecn(const char *ignored, int alsoignored) | |||
3916 | { | |||
3917 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
3918 | ifr.ifr_metricifr_ifru.ifru_metric = 0; | |||
3919 | if (ioctl(sock, SIOCSLIFPHYECN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((199))), (caddr_t)&ifr) == -1) | |||
3920 | warn("SIOCSLIFPHYECN"); | |||
3921 | } | |||
3922 | ||||
3923 | void | |||
3924 | setvnetflowid(const char *ignored, int alsoignored) | |||
3925 | { | |||
3926 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
3927 | sizeof(ifr.ifr_name)) | |||
3928 | errx(1, "vnetflowid: name is too long"); | |||
3929 | ||||
3930 | ifr.ifr_vnetidifr_ifru.ifru_vnetid = 1; | |||
3931 | if (ioctl(sock, SIOCSVNETFLOWID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((195))), &ifr) == -1) | |||
3932 | warn("SIOCSVNETFLOWID"); | |||
3933 | } | |||
3934 | ||||
3935 | void | |||
3936 | delvnetflowid(const char *ignored, int alsoignored) | |||
3937 | { | |||
3938 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
3939 | sizeof(ifr.ifr_name)) | |||
3940 | errx(1, "vnetflowid: name is too long"); | |||
3941 | ||||
3942 | ifr.ifr_vnetidifr_ifru.ifru_vnetid = 0; | |||
3943 | if (ioctl(sock, SIOCSVNETFLOWID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((195))), &ifr) == -1) | |||
3944 | warn("SIOCSVNETFLOWID"); | |||
3945 | } | |||
3946 | ||||
3947 | static void | |||
3948 | pwe3_neighbor(void) | |||
3949 | { | |||
3950 | const char *prefix = "pwe3 remote label"; | |||
3951 | struct if_laddrreq req; | |||
3952 | char hbuf[NI_MAXHOST256]; | |||
3953 | struct sockaddr_mpls *smpls; | |||
3954 | int error; | |||
3955 | ||||
3956 | memset(&req, 0, sizeof(req)); | |||
3957 | if (strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)) >= | |||
3958 | sizeof(req.iflr_name)) | |||
3959 | errx(1, "pwe3 neighbor: name is too long"); | |||
3960 | ||||
3961 | if (ioctl(sock, SIOCGPWE3NEIGHBOR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct if_laddrreq) & 0x1fff) << 16) | ((('i')) << 8) | ((222))), &req) == -1) { | |||
3962 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
3963 | return; | |||
3964 | ||||
3965 | printf(" %s (unset)", prefix); | |||
3966 | return; | |||
3967 | } | |||
3968 | ||||
3969 | if (req.dstaddr.ss_family != AF_MPLS33) { | |||
3970 | warnc(EPFNOSUPPORT46, "pwe3 neighbor"); | |||
3971 | return; | |||
3972 | } | |||
3973 | smpls = (struct sockaddr_mpls *)&req.dstaddr; | |||
3974 | ||||
3975 | error = getnameinfo((struct sockaddr *)&req.addr, sizeof(req.addr), | |||
3976 | hbuf, sizeof(hbuf), NULL((void *)0), 0, NI_NUMERICHOST1); | |||
3977 | if (error != 0) { | |||
3978 | warnx("%s: %s", prefix, gai_strerror(error)); | |||
3979 | return; | |||
3980 | } | |||
3981 | ||||
3982 | printf(" %s %u on %s", prefix, smpls->smpls_label, hbuf); | |||
3983 | } | |||
3984 | ||||
3985 | static void | |||
3986 | pwe3_cword(void) | |||
3987 | { | |||
3988 | struct ifreq req; | |||
3989 | ||||
3990 | memset(&req, 0, sizeof(req)); | |||
3991 | if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= | |||
3992 | sizeof(req.ifr_name)) | |||
3993 | errx(1, "pwe3 control word: name is too long"); | |||
3994 | ||||
3995 | if (ioctl(sock, SIOCGPWE3CTRLWORD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((220))), &req) == -1) { | |||
3996 | return; | |||
3997 | } | |||
3998 | ||||
3999 | printf(" %s", req.ifr_pwe3ifr_ifru.ifru_metric ? "cw" : "nocw"); | |||
4000 | } | |||
4001 | ||||
4002 | static void | |||
4003 | pwe3_fword(void) | |||
4004 | { | |||
4005 | struct ifreq req; | |||
4006 | ||||
4007 | memset(&req, 0, sizeof(req)); | |||
4008 | if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= | |||
4009 | sizeof(req.ifr_name)) | |||
4010 | errx(1, "pwe3 control word: name is too long"); | |||
4011 | ||||
4012 | if (ioctl(sock, SIOCGPWE3FAT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((221))), &req) == -1) | |||
4013 | return; | |||
4014 | ||||
4015 | printf(" %s", req.ifr_pwe3ifr_ifru.ifru_metric ? "fat" : "nofat"); | |||
4016 | } | |||
4017 | ||||
4018 | void | |||
4019 | mpls_status(void) | |||
4020 | { | |||
4021 | struct shim_hdr shim; | |||
4022 | ||||
4023 | bzero(&shim, sizeof(shim)); | |||
4024 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&shim; | |||
4025 | ||||
4026 | if (ioctl(sock, SIOCGETLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((154))), (caddr_t)&ifr) == -1) { | |||
4027 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
4028 | return; | |||
4029 | ||||
4030 | printf("\tmpls: label (unset)"); | |||
4031 | } else | |||
4032 | printf("\tmpls: label %u", shim.shim_label); | |||
4033 | ||||
4034 | pwe3_neighbor(); | |||
4035 | pwe3_cword(); | |||
4036 | pwe3_fword(); | |||
4037 | ||||
4038 | printf("\n"); | |||
4039 | } | |||
4040 | ||||
4041 | void | |||
4042 | setmplslabel(const char *val, int d) | |||
4043 | { | |||
4044 | struct shim_hdr shim; | |||
4045 | const char *estr; | |||
4046 | ||||
4047 | bzero(&shim, sizeof(shim)); | |||
4048 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&shim; | |||
4049 | shim.shim_label = strtonum(val, 0, MPLS_LABEL_MAX((1 << 20) - 1), &estr); | |||
4050 | ||||
4051 | if (estr) | |||
4052 | errx(1, "mpls label %s is %s", val, estr); | |||
4053 | if (ioctl(sock, SIOCSETLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((153))), (caddr_t)&ifr) == -1) | |||
4054 | warn("SIOCSETLABEL"); | |||
4055 | } | |||
4056 | ||||
4057 | void | |||
4058 | unsetmplslabel(const char *val, int d) | |||
4059 | { | |||
4060 | struct ifreq req; | |||
4061 | ||||
4062 | memset(&req, 0, sizeof(req)); | |||
4063 | if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= | |||
4064 | sizeof(req.ifr_name)) | |||
4065 | errx(1, "interface name is too long"); | |||
4066 | ||||
4067 | if (ioctl(sock, SIOCDELLABEL((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((151))), (caddr_t)&ifr) == -1) | |||
4068 | warn("-mplslabel"); | |||
4069 | } | |||
4070 | ||||
4071 | static void | |||
4072 | setpwe3(unsigned long cmd, const char *cmdname, int value) | |||
4073 | { | |||
4074 | struct ifreq req; | |||
4075 | ||||
4076 | memset(&req, 0, sizeof(req)); | |||
4077 | if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= | |||
4078 | sizeof(req.ifr_name)) | |||
4079 | errx(1, "interface name is too long"); | |||
4080 | ||||
4081 | req.ifr_pwe3ifr_ifru.ifru_metric = value; | |||
4082 | ||||
4083 | if (ioctl(sock, cmd, &req) == -1) | |||
4084 | warn("%s", cmdname); | |||
4085 | } | |||
4086 | ||||
4087 | void | |||
4088 | setpwe3cw(const char *val, int d) | |||
4089 | { | |||
4090 | setpwe3(SIOCSPWE3CTRLWORD((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((220))), "pwecw", 1); | |||
4091 | } | |||
4092 | ||||
4093 | void | |||
4094 | unsetpwe3cw(const char *val, int d) | |||
4095 | { | |||
4096 | setpwe3(SIOCSPWE3CTRLWORD((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((220))), "-pwecw", 0); | |||
4097 | } | |||
4098 | ||||
4099 | void | |||
4100 | setpwe3fat(const char *val, int d) | |||
4101 | { | |||
4102 | setpwe3(SIOCSPWE3FAT((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((221))), "pwefat", 1); | |||
4103 | } | |||
4104 | ||||
4105 | void | |||
4106 | unsetpwe3fat(const char *val, int d) | |||
4107 | { | |||
4108 | setpwe3(SIOCSPWE3FAT((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((221))), "-pwefat", 0); | |||
4109 | } | |||
4110 | ||||
4111 | void | |||
4112 | setpwe3neighbor(const char *label, const char *neighbor) | |||
4113 | { | |||
4114 | struct if_laddrreq req; | |||
4115 | struct addrinfo hints, *res; | |||
4116 | struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)&req.dstaddr; | |||
4117 | const char *errstr; | |||
4118 | int error; | |||
4119 | ||||
4120 | memset(&req, 0, sizeof(req)); | |||
4121 | if (strlcpy(req.iflr_name, ifname, sizeof(req.iflr_name)) >= | |||
4122 | sizeof(req.iflr_name)) | |||
4123 | errx(1, "interface name is too long"); | |||
4124 | ||||
4125 | memset(&hints, 0, sizeof(hints)); | |||
4126 | hints.ai_family = AF_UNSPEC0; | |||
4127 | hints.ai_socktype = SOCK_DGRAM2; | |||
4128 | error = getaddrinfo(neighbor, NULL((void *)0), &hints, &res); | |||
4129 | if (error != 0) | |||
4130 | errx(1, "pweneighbor %s: %s", neighbor, gai_strerror(error)); | |||
4131 | ||||
4132 | smpls->smpls_len = sizeof(*smpls); | |||
4133 | smpls->smpls_family = AF_MPLS33; | |||
4134 | smpls->smpls_label = strtonum(label, | |||
4135 | (MPLS_LABEL_RESERVED_MAX15 + 1), MPLS_LABEL_MAX((1 << 20) - 1), &errstr); | |||
4136 | if (errstr != NULL((void *)0)) | |||
4137 | errx(1, "pweneighbor: invalid label: %s", errstr); | |||
4138 | ||||
4139 | ||||
4140 | if (res->ai_addrlen > sizeof(req.addr)) | |||
4141 | errx(1, "pweneighbors: unexpected socklen"); | |||
4142 | ||||
4143 | memcpy(&req.addr, res->ai_addr, res->ai_addrlen); | |||
4144 | ||||
4145 | freeaddrinfo(res); | |||
4146 | ||||
4147 | if (ioctl(sock, SIOCSPWE3NEIGHBOR((unsigned long)0x80000000 | ((sizeof(struct if_laddrreq) & 0x1fff) << 16) | ((('i')) << 8) | ((222))), &req) == -1) | |||
4148 | warn("pweneighbor"); | |||
4149 | } | |||
4150 | ||||
4151 | void | |||
4152 | unsetpwe3neighbor(const char *val, int d) | |||
4153 | { | |||
4154 | struct ifreq req; | |||
4155 | ||||
4156 | memset(&req, 0, sizeof(req)); | |||
4157 | if (strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name)) >= | |||
4158 | sizeof(req.ifr_name)) | |||
4159 | errx(1, "interface name is too long"); | |||
4160 | ||||
4161 | if (ioctl(sock, SIOCDPWE3NEIGHBOR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((222))), &req) == -1) | |||
4162 | warn("-pweneighbor"); | |||
4163 | } | |||
4164 | ||||
4165 | void | |||
4166 | transceiver(const char *value, int d) | |||
4167 | { | |||
4168 | showtransceiver = 1; | |||
4169 | } | |||
4170 | ||||
4171 | void | |||
4172 | transceiverdump(const char *value, int d) | |||
4173 | { | |||
4174 | if (if_sff_info(1) == -1) | |||
4175 | err(1, "%s transceiver", ifname); | |||
4176 | } | |||
4177 | #endif /* SMALL */ | |||
4178 | ||||
4179 | void | |||
4180 | getvnetflowid(struct ifencap *ife) | |||
4181 | { | |||
4182 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
4183 | sizeof(ifr.ifr_name)) | |||
4184 | errx(1, "vnetflowid: name is too long"); | |||
4185 | ||||
4186 | if (ioctl(sock, SIOCGVNETFLOWID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((196))), &ifr) == -1) | |||
4187 | return; | |||
4188 | ||||
4189 | if (ifr.ifr_vnetidifr_ifru.ifru_vnetid) | |||
4190 | ife->ife_flags |= IFE_VNETFLOWID0x10; | |||
4191 | } | |||
4192 | ||||
4193 | void | |||
4194 | setvnetid(const char *id, int param) | |||
4195 | { | |||
4196 | const char *errmsg = NULL((void *)0); | |||
4197 | int64_t vnetid; | |||
4198 | ||||
4199 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
4200 | ||||
4201 | if (strcasecmp("any", id) == 0) | |||
4202 | vnetid = -1; | |||
4203 | else { | |||
4204 | vnetid = strtonum(id, 0, INT64_MAX0x7fffffffffffffffLL, &errmsg); | |||
4205 | if (errmsg) | |||
4206 | errx(1, "vnetid %s: %s", id, errmsg); | |||
4207 | } | |||
4208 | ||||
4209 | ifr.ifr_vnetidifr_ifru.ifru_vnetid = vnetid; | |||
4210 | if (ioctl(sock, SIOCSVNETID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((166))), (caddr_t)&ifr) == -1) | |||
4211 | warn("SIOCSVNETID"); | |||
4212 | } | |||
4213 | ||||
4214 | void | |||
4215 | delvnetid(const char *ignored, int alsoignored) | |||
4216 | { | |||
4217 | if (ioctl(sock, SIOCDVNETID((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((175))), &ifr) == -1) | |||
4218 | warn("SIOCDVNETID"); | |||
4219 | } | |||
4220 | ||||
4221 | void | |||
4222 | getvnetid(struct ifencap *ife) | |||
4223 | { | |||
4224 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
4225 | sizeof(ifr.ifr_name)) | |||
4226 | errx(1, "vnetid: name is too long"); | |||
4227 | ||||
4228 | if (ioctl(sock, SIOCGVNETID(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((167))), &ifr) == -1) { | |||
4229 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
4230 | return; | |||
4231 | ||||
4232 | ife->ife_flags |= IFE_VNETID_NONE0x1; | |||
4233 | return; | |||
4234 | } | |||
4235 | ||||
4236 | if (ifr.ifr_vnetidifr_ifru.ifru_vnetid < 0) { | |||
4237 | ife->ife_flags |= IFE_VNETID_ANY0x2; | |||
4238 | return; | |||
4239 | } | |||
4240 | ||||
4241 | ife->ife_flags |= IFE_VNETID_SET0x3; | |||
4242 | ife->ife_vnetid = ifr.ifr_vnetidifr_ifru.ifru_vnetid; | |||
4243 | } | |||
4244 | ||||
4245 | void | |||
4246 | setifparent(const char *id, int param) | |||
4247 | { | |||
4248 | struct if_parent ifp; | |||
4249 | ||||
4250 | if (strlcpy(ifp.ifp_name, ifname, sizeof(ifp.ifp_name)) >= | |||
4251 | sizeof(ifp.ifp_name)) | |||
4252 | errx(1, "parent: name too long"); | |||
4253 | ||||
4254 | if (strlcpy(ifp.ifp_parent, id, sizeof(ifp.ifp_parent)) >= | |||
4255 | sizeof(ifp.ifp_parent)) | |||
4256 | errx(1, "parent: parent too long"); | |||
4257 | ||||
4258 | if (ioctl(sock, SIOCSIFPARENT((unsigned long)0x80000000 | ((sizeof(struct if_parent) & 0x1fff) << 16) | ((('i')) << 8) | ((178))), (caddr_t)&ifp) == -1) | |||
4259 | warn("%s: %s: SIOCSIFPARENT", ifp.ifp_name, ifp.ifp_parent); | |||
4260 | } | |||
4261 | ||||
4262 | void | |||
4263 | delifparent(const char *ignored, int alsoignored) | |||
4264 | { | |||
4265 | if (ioctl(sock, SIOCDIFPARENT((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((180))), &ifr) == -1) | |||
4266 | warn("SIOCDIFPARENT"); | |||
4267 | } | |||
4268 | ||||
4269 | void | |||
4270 | getifparent(struct ifencap *ife) | |||
4271 | { | |||
4272 | struct if_parent ifp; | |||
4273 | ||||
4274 | memset(&ifp, 0, sizeof(ifp)); | |||
4275 | if (strlcpy(ifp.ifp_name, ifname, sizeof(ifp.ifp_name)) >= | |||
4276 | sizeof(ifp.ifp_name)) | |||
4277 | errx(1, "parent: name too long"); | |||
4278 | ||||
4279 | if (ioctl(sock, SIOCGIFPARENT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct if_parent) & 0x1fff) << 16) | ((('i')) << 8) | ((179))), (caddr_t)&ifp) == -1) { | |||
4280 | if (errno(*__errno()) != EADDRNOTAVAIL49) | |||
4281 | return; | |||
4282 | ||||
4283 | ife->ife_flags |= IFE_PARENT_NONE0x100; | |||
4284 | } else { | |||
4285 | memcpy(ife->ife_parent, ifp.ifp_parent, | |||
4286 | sizeof(ife->ife_parent)); | |||
4287 | ife->ife_flags |= IFE_PARENT_SET0x200; | |||
4288 | } | |||
4289 | } | |||
4290 | ||||
4291 | #ifndef SMALL | |||
4292 | void | |||
4293 | gettxprio(struct ifencap *ife) | |||
4294 | { | |||
4295 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
4296 | sizeof(ifr.ifr_name)) | |||
4297 | errx(1, "hdr prio: name is too long"); | |||
4298 | ||||
4299 | if (ioctl(sock, SIOCGTXHPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((198))), (caddr_t)&ifr) == -1) | |||
4300 | return; | |||
4301 | ||||
4302 | ife->ife_flags |= IFE_TXHPRIO_SET0x1000; | |||
4303 | ife->ife_txhprio = ifr.ifr_hdrprioifr_ifru.ifru_metric; | |||
4304 | } | |||
4305 | ||||
4306 | void | |||
4307 | settxprio(const char *val, int d) | |||
4308 | { | |||
4309 | const char *errmsg = NULL((void *)0); | |||
4310 | ||||
4311 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
4312 | sizeof(ifr.ifr_name)) | |||
4313 | errx(1, "tx prio: name is too long"); | |||
4314 | ||||
4315 | if (strcmp(val, "packet") == 0) | |||
4316 | ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PACKET-1; | |||
4317 | else if (strcmp(val, "payload") == 0) | |||
4318 | ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PAYLOAD-2; | |||
4319 | else { | |||
4320 | ifr.ifr_hdrprioifr_ifru.ifru_metric = strtonum(val, | |||
4321 | IF_HDRPRIO_MIN0, IF_HDRPRIO_MAX8 - 1, &errmsg); | |||
4322 | if (errmsg) | |||
4323 | errx(1, "tx prio %s: %s", val, errmsg); | |||
4324 | } | |||
4325 | ||||
4326 | if (ioctl(sock, SIOCSTXHPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((197))), (caddr_t)&ifr) == -1) | |||
4327 | warn("SIOCSTXHPRIO"); | |||
4328 | } | |||
4329 | ||||
4330 | void | |||
4331 | getrxprio(struct ifencap *ife) | |||
4332 | { | |||
4333 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
4334 | sizeof(ifr.ifr_name)) | |||
4335 | errx(1, "hdr prio: name is too long"); | |||
4336 | ||||
4337 | if (ioctl(sock, SIOCGRXHPRIO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((219))), (caddr_t)&ifr) == -1) | |||
4338 | return; | |||
4339 | ||||
4340 | ife->ife_flags |= IFE_RXHPRIO_SET0x2000; | |||
4341 | ife->ife_rxhprio = ifr.ifr_hdrprioifr_ifru.ifru_metric; | |||
4342 | } | |||
4343 | ||||
4344 | void | |||
4345 | setrxprio(const char *val, int d) | |||
4346 | { | |||
4347 | const char *errmsg = NULL((void *)0); | |||
4348 | ||||
4349 | if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >= | |||
4350 | sizeof(ifr.ifr_name)) | |||
4351 | errx(1, "rx prio: name is too long"); | |||
4352 | ||||
4353 | if (strcmp(val, "packet") == 0) | |||
4354 | ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PACKET-1; | |||
4355 | else if (strcmp(val, "payload") == 0) | |||
4356 | ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_PAYLOAD-2; | |||
4357 | else if (strcmp(val, "outer") == 0) | |||
4358 | ifr.ifr_hdrprioifr_ifru.ifru_metric = IF_HDRPRIO_OUTER-3; | |||
4359 | else { | |||
4360 | ifr.ifr_hdrprioifr_ifru.ifru_metric = strtonum(val, | |||
4361 | IF_HDRPRIO_MIN0, IF_HDRPRIO_MAX8 - 1, &errmsg); | |||
4362 | if (errmsg) | |||
4363 | errx(1, "rx prio %s: %s", val, errmsg); | |||
4364 | } | |||
4365 | ||||
4366 | if (ioctl(sock, SIOCSRXHPRIO((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((219))), (caddr_t)&ifr) == -1) | |||
4367 | warn("SIOCSRXHPRIO"); | |||
4368 | } | |||
4369 | #endif | |||
4370 | ||||
4371 | void | |||
4372 | getencap(void) | |||
4373 | { | |||
4374 | struct ifencap ife = { .ife_flags = 0 }; | |||
4375 | ||||
4376 | getvnetid(&ife); | |||
4377 | getvnetflowid(&ife); | |||
4378 | getifparent(&ife); | |||
4379 | #ifndef SMALL | |||
4380 | gettxprio(&ife); | |||
4381 | getrxprio(&ife); | |||
4382 | #endif | |||
4383 | ||||
4384 | if (ife.ife_flags == 0) | |||
4385 | return; | |||
4386 | ||||
4387 | printf("\tencap:"); | |||
4388 | ||||
4389 | switch (ife.ife_flags & IFE_VNETID_MASK0xf) { | |||
4390 | case IFE_VNETID_NONE0x1: | |||
4391 | printf(" vnetid none"); | |||
4392 | break; | |||
4393 | case IFE_VNETID_ANY0x2: | |||
4394 | printf(" vnetid any"); | |||
4395 | break; | |||
4396 | case IFE_VNETID_SET0x3: | |||
4397 | printf(" vnetid %lld", ife.ife_vnetid); | |||
4398 | if (ife.ife_flags & IFE_VNETFLOWID0x10) | |||
4399 | printf("+"); | |||
4400 | break; | |||
4401 | } | |||
4402 | ||||
4403 | switch (ife.ife_flags & IFE_PARENT_MASK0xf00) { | |||
4404 | case IFE_PARENT_NONE0x100: | |||
4405 | printf(" parent none"); | |||
4406 | break; | |||
4407 | case IFE_PARENT_SET0x200: | |||
4408 | printf(" parent %s", ife.ife_parent); | |||
4409 | break; | |||
4410 | } | |||
4411 | ||||
4412 | #ifndef SMALL | |||
4413 | if (ife.ife_flags & IFE_TXHPRIO_SET0x1000) { | |||
4414 | printf(" txprio "); | |||
4415 | switch (ife.ife_txhprio) { | |||
4416 | case IF_HDRPRIO_PACKET-1: | |||
4417 | printf("packet"); | |||
4418 | break; | |||
4419 | case IF_HDRPRIO_PAYLOAD-2: | |||
4420 | printf("payload"); | |||
4421 | break; | |||
4422 | default: | |||
4423 | printf("%d", ife.ife_txhprio); | |||
4424 | break; | |||
4425 | } | |||
4426 | } | |||
4427 | ||||
4428 | if (ife.ife_flags & IFE_RXHPRIO_SET0x2000) { | |||
4429 | printf(" rxprio "); | |||
4430 | switch (ife.ife_rxhprio) { | |||
4431 | case IF_HDRPRIO_PACKET-1: | |||
4432 | printf("packet"); | |||
4433 | break; | |||
4434 | case IF_HDRPRIO_PAYLOAD-2: | |||
4435 | printf("payload"); | |||
4436 | break; | |||
4437 | case IF_HDRPRIO_OUTER-3: | |||
4438 | printf("outer"); | |||
4439 | break; | |||
4440 | default: | |||
4441 | printf("%d", ife.ife_rxhprio); | |||
4442 | break; | |||
4443 | } | |||
4444 | } | |||
4445 | #endif | |||
4446 | ||||
4447 | printf("\n"); | |||
4448 | } | |||
4449 | ||||
4450 | void | |||
4451 | settrunkport(const char *val, int d) | |||
4452 | { | |||
4453 | struct trunk_reqport rp; | |||
4454 | ||||
4455 | bzero(&rp, sizeof(rp)); | |||
4456 | strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname)); | |||
4457 | strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); | |||
4458 | ||||
4459 | if (ioctl(sock, SIOCSTRUNKPORT((unsigned long)0x80000000 | ((sizeof(struct trunk_reqport) & 0x1fff) << 16) | ((('i')) << 8) | ((141))), &rp) == -1) | |||
4460 | err(1, "%s %s: SIOCSTRUNKPORT", rp.rp_ifname, rp.rp_portname); | |||
4461 | } | |||
4462 | ||||
4463 | void | |||
4464 | unsettrunkport(const char *val, int d) | |||
4465 | { | |||
4466 | struct trunk_reqport rp; | |||
4467 | ||||
4468 | bzero(&rp, sizeof(rp)); | |||
4469 | strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname)); | |||
4470 | strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname)); | |||
4471 | ||||
4472 | if (ioctl(sock, SIOCSTRUNKDELPORT((unsigned long)0x80000000 | ((sizeof(struct trunk_reqport) & 0x1fff) << 16) | ((('i')) << 8) | ((142))), &rp) == -1) | |||
4473 | err(1, "%s: %s: SIOCSTRUNKDELPORT", rp.rp_ifname, | |||
4474 | rp.rp_portname); | |||
4475 | } | |||
4476 | ||||
4477 | void | |||
4478 | settrunkproto(const char *val, int d) | |||
4479 | { | |||
4480 | struct trunk_protos tpr[] = TRUNK_PROTOS{ { "roundrobin", TRUNK_PROTO_ROUNDROBIN }, { "failover", TRUNK_PROTO_FAILOVER }, { "lacp", TRUNK_PROTO_LACP }, { "loadbalance", TRUNK_PROTO_LOADBALANCE }, { "broadcast", TRUNK_PROTO_BROADCAST }, { "none", TRUNK_PROTO_NONE }, { "default", TRUNK_PROTO_ROUNDROBIN } }; | |||
4481 | struct trunk_reqall ra; | |||
4482 | int i; | |||
4483 | ||||
4484 | bzero(&ra, sizeof(ra)); | |||
4485 | ra.ra_proto = TRUNK_PROTO_MAX; | |||
4486 | ||||
4487 | for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) { | |||
4488 | if (strcmp(val, tpr[i].tpr_name) == 0) { | |||
4489 | ra.ra_proto = tpr[i].tpr_proto; | |||
4490 | break; | |||
4491 | } | |||
4492 | } | |||
4493 | if (ra.ra_proto == TRUNK_PROTO_MAX) | |||
4494 | errx(1, "Invalid trunk protocol: %s", val); | |||
4495 | ||||
4496 | strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); | |||
4497 | if (ioctl(sock, SIOCSTRUNK((unsigned long)0x80000000 | ((sizeof(struct trunk_reqall) & 0x1fff) << 16) | ((('i')) << 8) | ((144))), &ra) != 0) | |||
4498 | err(1, "%s: SIOCSTRUNK", ra.ra_ifname); | |||
4499 | } | |||
4500 | ||||
4501 | void | |||
4502 | settrunklacpmode(const char *val, int d) | |||
4503 | { | |||
4504 | struct trunk_reqall ra; | |||
4505 | struct trunk_opts tops; | |||
4506 | ||||
4507 | bzero(&ra, sizeof(ra)); | |||
4508 | strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); | |||
4509 | ||||
4510 | if (ioctl(sock, SIOCGTRUNK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct trunk_reqall) & 0x1fff) << 16) | ((('i')) << 8) | ((143))), &ra) != 0) | |||
4511 | err(1, "%s: SIOCGTRUNK", ra.ra_ifname); | |||
4512 | ||||
4513 | if (ra.ra_proto != TRUNK_PROTO_LACP) | |||
4514 | errx(1, "Invalid option for trunk: %s", ifname); | |||
4515 | ||||
4516 | if (strcmp(val, lacpmodeactive) != 0 && | |||
4517 | strcmp(val, lacpmodepassive) != 0) | |||
4518 | errx(1, "Invalid lacpmode option for trunk: %s", ifname); | |||
4519 | ||||
4520 | bzero(&tops, sizeof(tops)); | |||
4521 | strlcpy(tops.to_ifname, ifname, sizeof(tops.to_ifname)); | |||
4522 | tops.to_proto = TRUNK_PROTO_LACP; | |||
4523 | tops.to_opts |= TRUNK_OPT_LACP_MODE0x01; | |||
4524 | ||||
4525 | if (strcmp(val, lacpmodeactive) == 0) | |||
4526 | tops.to_lacpoptsto_psc.rpsc_lacp.lacp_mode = 1; | |||
4527 | else | |||
4528 | tops.to_lacpoptsto_psc.rpsc_lacp.lacp_mode = 0; | |||
4529 | ||||
4530 | if (ioctl(sock, SIOCSTRUNKOPTS((unsigned long)0x80000000 | ((sizeof(struct trunk_opts) & 0x1fff) << 16) | ((('i')) << 8) | ((146))), &tops) != 0) | |||
4531 | err(1, "%s: SIOCSTRUNKOPTS", tops.to_ifname); | |||
4532 | } | |||
4533 | ||||
4534 | void | |||
4535 | settrunklacptimeout(const char *val, int d) | |||
4536 | { | |||
4537 | struct trunk_reqall ra; | |||
4538 | struct trunk_opts tops; | |||
4539 | ||||
4540 | bzero(&ra, sizeof(ra)); | |||
4541 | strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); | |||
4542 | ||||
4543 | if (ioctl(sock, SIOCGTRUNK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct trunk_reqall) & 0x1fff) << 16) | ((('i')) << 8) | ((143))), &ra) != 0) | |||
4544 | err(1, "%s SIOCGTRUNK", ra.ra_ifname); | |||
4545 | ||||
4546 | if (ra.ra_proto != TRUNK_PROTO_LACP) | |||
4547 | errx(1, "Invalid option for trunk: %s", ifname); | |||
4548 | ||||
4549 | if (strcmp(val, lacptimeoutfast) != 0 && | |||
4550 | strcmp(val, lacptimeoutslow) != 0) | |||
4551 | errx(1, "Invalid lacptimeout option for trunk: %s", ifname); | |||
4552 | ||||
4553 | bzero(&tops, sizeof(tops)); | |||
4554 | strlcpy(tops.to_ifname, ifname, sizeof(tops.to_ifname)); | |||
4555 | tops.to_proto = TRUNK_PROTO_LACP; | |||
4556 | tops.to_opts |= TRUNK_OPT_LACP_TIMEOUT0x02; | |||
4557 | ||||
4558 | if (strcmp(val, lacptimeoutfast) == 0) | |||
4559 | tops.to_lacpoptsto_psc.rpsc_lacp.lacp_timeout = 1; | |||
4560 | else | |||
4561 | tops.to_lacpoptsto_psc.rpsc_lacp.lacp_timeout = 0; | |||
4562 | ||||
4563 | if (ioctl(sock, SIOCSTRUNKOPTS((unsigned long)0x80000000 | ((sizeof(struct trunk_opts) & 0x1fff) << 16) | ((('i')) << 8) | ((146))), &tops) != 0) | |||
4564 | err(1, "%s: SIOCSTRUNKOPTS", tops.to_ifname); | |||
4565 | } | |||
4566 | ||||
4567 | void | |||
4568 | trunk_status(void) | |||
4569 | { | |||
4570 | struct trunk_protos tpr[] = TRUNK_PROTOS{ { "roundrobin", TRUNK_PROTO_ROUNDROBIN }, { "failover", TRUNK_PROTO_FAILOVER }, { "lacp", TRUNK_PROTO_LACP }, { "loadbalance", TRUNK_PROTO_LOADBALANCE }, { "broadcast", TRUNK_PROTO_BROADCAST }, { "none", TRUNK_PROTO_NONE }, { "default", TRUNK_PROTO_ROUNDROBIN } }; | |||
4571 | struct trunk_reqport rp, rpbuf[TRUNK_MAX_PORTS32]; | |||
4572 | struct trunk_reqall ra; | |||
4573 | struct lacp_opreq *lp; | |||
4574 | const char *proto = "<unknown>"; | |||
4575 | int i, isport = 0; | |||
4576 | ||||
4577 | bzero(&rp, sizeof(rp)); | |||
4578 | bzero(&ra, sizeof(ra)); | |||
4579 | ||||
4580 | strlcpy(rp.rp_ifname, ifname, sizeof(rp.rp_ifname)); | |||
4581 | strlcpy(rp.rp_portname, ifname, sizeof(rp.rp_portname)); | |||
4582 | ||||
4583 | if (ioctl(sock, SIOCGTRUNKPORT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct trunk_reqport) & 0x1fff) << 16) | ((('i')) << 8) | ((140))), &rp) == 0) | |||
4584 | isport = 1; | |||
4585 | ||||
4586 | strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); | |||
4587 | ra.ra_size = sizeof(rpbuf); | |||
4588 | ra.ra_port = rpbuf; | |||
4589 | ||||
4590 | if (ioctl(sock, SIOCGTRUNK(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct trunk_reqall) & 0x1fff) << 16) | ((('i')) << 8) | ((143))), &ra) == 0) { | |||
4591 | lp = (struct lacp_opreq *)&ra.ra_lacpreqra_psc.rpsc_lacp; | |||
4592 | ||||
4593 | for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) { | |||
4594 | if (ra.ra_proto == tpr[i].tpr_proto) { | |||
4595 | proto = tpr[i].tpr_name; | |||
4596 | break; | |||
4597 | } | |||
4598 | } | |||
4599 | ||||
4600 | printf("\ttrunk: trunkproto %s", proto); | |||
4601 | if (isport) | |||
4602 | printf(" trunkdev %s", rp.rp_ifname); | |||
4603 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
4604 | if (ra.ra_proto == TRUNK_PROTO_LACP) { | |||
4605 | char *act_mac = strdup( | |||
4606 | ether_ntoa((struct ether_addr*)lp->actor_mac)); | |||
4607 | if (act_mac == NULL((void *)0)) | |||
4608 | err(1, "strdup"); | |||
4609 | printf("\ttrunk id: [(%04X,%s,%04X,%04X,%04X),\n" | |||
4610 | "\t\t (%04X,%s,%04X,%04X,%04X)]\n", | |||
4611 | lp->actor_prio, act_mac, | |||
4612 | lp->actor_key, lp->actor_portprio, lp->actor_portno, | |||
4613 | lp->partner_prio, | |||
4614 | ether_ntoa((struct ether_addr*)lp->partner_mac), | |||
4615 | lp->partner_key, lp->partner_portprio, | |||
4616 | lp->partner_portno); | |||
4617 | free(act_mac); | |||
4618 | } | |||
4619 | ||||
4620 | for (i = 0; i < ra.ra_ports; i++) { | |||
4621 | lp = (struct lacp_opreq *)&(rpbuf[i].rp_lacpreqrp_psc.rpsc_lacp); | |||
4622 | if (ra.ra_proto == TRUNK_PROTO_LACP) { | |||
4623 | printf("\t\t%s lacp actor " | |||
4624 | "system pri 0x%x mac %s, key 0x%x, " | |||
4625 | "port pri 0x%x number 0x%x\n", | |||
4626 | rpbuf[i].rp_portname, | |||
4627 | lp->actor_prio, | |||
4628 | ether_ntoa((struct ether_addr*) | |||
4629 | lp->actor_mac), | |||
4630 | lp->actor_key, | |||
4631 | lp->actor_portprio, lp->actor_portno); | |||
4632 | printf("\t\t%s lacp actor state ", | |||
4633 | rpbuf[i].rp_portname); | |||
4634 | printb_status(lp->actor_state, | |||
4635 | LACP_STATE_BITS"\020" "\001ACTIVITY" "\002TIMEOUT" "\003AGGREGATION" "\004SYNC" "\005COLLECTING" "\006DISTRIBUTING" "\007DEFAULTED" "\010EXPIRED"); | |||
4636 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
4637 | ||||
4638 | printf("\t\t%s lacp partner " | |||
4639 | "system pri 0x%x mac %s, key 0x%x, " | |||
4640 | "port pri 0x%x number 0x%x\n", | |||
4641 | rpbuf[i].rp_portname, | |||
4642 | lp->partner_prio, | |||
4643 | ether_ntoa((struct ether_addr*) | |||
4644 | lp->partner_mac), | |||
4645 | lp->partner_key, | |||
4646 | lp->partner_portprio, lp->partner_portno); | |||
4647 | printf("\t\t%s lacp partner state ", | |||
4648 | rpbuf[i].rp_portname); | |||
4649 | printb_status(lp->partner_state, | |||
4650 | LACP_STATE_BITS"\020" "\001ACTIVITY" "\002TIMEOUT" "\003AGGREGATION" "\004SYNC" "\005COLLECTING" "\006DISTRIBUTING" "\007DEFAULTED" "\010EXPIRED"); | |||
4651 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
4652 | } | |||
4653 | ||||
4654 | printf("\t\t%s port ", rpbuf[i].rp_portname); | |||
4655 | printb_status(rpbuf[i].rp_flags, TRUNK_PORT_BITS"\20\01MASTER\02STACK\03ACTIVE" "\04COLLECTING\05DISTRIBUTING\06DISABLED"); | |||
4656 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
4657 | } | |||
4658 | ||||
4659 | if (showmediaflag) { | |||
4660 | printf("\tsupported trunk protocols:\n"); | |||
4661 | for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) | |||
4662 | printf("\t\ttrunkproto %s\n", tpr[i].tpr_name); | |||
4663 | } | |||
4664 | } else if (isport) | |||
4665 | printf("\ttrunk: trunkdev %s\n", rp.rp_ifname); | |||
4666 | } | |||
4667 | ||||
4668 | #ifndef SMALL | |||
4669 | static const char *carp_states[] = { CARP_STATES"INIT", "BACKUP", "MASTER" }; | |||
4670 | static const char *carp_bal_modes[] = { CARP_BAL_MODES"none", "ip", "ip-stealth", "ip-unicast" }; | |||
4671 | ||||
4672 | void | |||
4673 | carp_status(void) | |||
4674 | { | |||
4675 | const char *state, *balmode; | |||
4676 | struct carpreq carpr; | |||
4677 | char peer[32]; | |||
4678 | int i; | |||
4679 | ||||
4680 | memset((char *)&carpr, 0, sizeof(struct carpreq)); | |||
4681 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4682 | ||||
4683 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4684 | return; | |||
4685 | ||||
4686 | if (carpr.carpr_vhids[0] == 0) | |||
4687 | return; | |||
4688 | ||||
4689 | if (carpr.carpr_balancing > CARP_BAL_MAXID3) | |||
4690 | balmode = "<UNKNOWN>"; | |||
4691 | else | |||
4692 | balmode = carp_bal_modes[carpr.carpr_balancing]; | |||
4693 | ||||
4694 | if (carpr.carpr_peer.s_addr != htonl(INADDR_CARP_GROUP)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0xe0000012))) ? (__uint32_t)(((__uint32_t)(((u_int32_t)(0xe0000012))) & 0xff ) << 24 | ((__uint32_t)(((u_int32_t)(0xe0000012))) & 0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0xe0000012)) ) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0xe0000012 ))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)( 0xe0000012))))) | |||
4695 | snprintf(peer, sizeof(peer), | |||
4696 | " carppeer %s", inet_ntoa(carpr.carpr_peer)); | |||
4697 | else | |||
4698 | peer[0] = '\0'; | |||
4699 | ||||
4700 | for (i = 0; carpr.carpr_vhids[i]; i++) { | |||
4701 | if (carpr.carpr_states[i] > CARP_MAXSTATE2) | |||
4702 | state = "<UNKNOWN>"; | |||
4703 | else | |||
4704 | state = carp_states[carpr.carpr_states[i]]; | |||
4705 | if (carpr.carpr_vhids[1] == 0) { | |||
4706 | printf("\tcarp: %s carpdev %s vhid %u advbase %d " | |||
4707 | "advskew %u%s\n", state, | |||
4708 | carpr.carpr_carpdev[0] != '\0' ? | |||
4709 | carpr.carpr_carpdev : "none", carpr.carpr_vhids[0], | |||
4710 | carpr.carpr_advbase, carpr.carpr_advskews[0], | |||
4711 | peer); | |||
4712 | } else { | |||
4713 | if (i == 0) { | |||
4714 | printf("\tcarp: carpdev %s advbase %d" | |||
4715 | " balancing %s%s\n", | |||
4716 | carpr.carpr_carpdev[0] != '\0' ? | |||
4717 | carpr.carpr_carpdev : "none", | |||
4718 | carpr.carpr_advbase, balmode, peer); | |||
4719 | } | |||
4720 | printf("\t\tstate %s vhid %u advskew %u\n", state, | |||
4721 | carpr.carpr_vhids[i], carpr.carpr_advskews[i]); | |||
4722 | } | |||
4723 | } | |||
4724 | } | |||
4725 | ||||
4726 | void | |||
4727 | setcarp_passwd(const char *val, int d) | |||
4728 | { | |||
4729 | struct carpreq carpr; | |||
4730 | ||||
4731 | bzero(&carpr, sizeof(struct carpreq)); | |||
4732 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4733 | ||||
4734 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4735 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4736 | ||||
4737 | bzero(carpr.carpr_key, CARP_KEY_LEN20); | |||
4738 | strlcpy((char *)carpr.carpr_key, val, CARP_KEY_LEN20); | |||
4739 | ||||
4740 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4741 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4742 | } | |||
4743 | ||||
4744 | void | |||
4745 | setcarp_vhid(const char *val, int d) | |||
4746 | { | |||
4747 | const char *errmsg = NULL((void *)0); | |||
4748 | struct carpreq carpr; | |||
4749 | int vhid; | |||
4750 | ||||
4751 | vhid = strtonum(val, 1, 255, &errmsg); | |||
4752 | if (errmsg) | |||
4753 | errx(1, "vhid %s: %s", val, errmsg); | |||
4754 | ||||
4755 | bzero(&carpr, sizeof(struct carpreq)); | |||
4756 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4757 | ||||
4758 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4759 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4760 | ||||
4761 | carpr.carpr_vhids[0] = vhid; | |||
4762 | carpr.carpr_vhids[1] = 0; | |||
4763 | ||||
4764 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4765 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4766 | } | |||
4767 | ||||
4768 | void | |||
4769 | setcarp_advskew(const char *val, int d) | |||
4770 | { | |||
4771 | const char *errmsg = NULL((void *)0); | |||
4772 | struct carpreq carpr; | |||
4773 | int advskew; | |||
4774 | ||||
4775 | advskew = strtonum(val, 0, 254, &errmsg); | |||
4776 | if (errmsg) | |||
4777 | errx(1, "advskew %s: %s", val, errmsg); | |||
4778 | ||||
4779 | bzero(&carpr, sizeof(struct carpreq)); | |||
4780 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4781 | ||||
4782 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4783 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4784 | ||||
4785 | carpr.carpr_advskews[0] = advskew; | |||
4786 | ||||
4787 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4788 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4789 | } | |||
4790 | ||||
4791 | void | |||
4792 | setcarp_advbase(const char *val, int d) | |||
4793 | { | |||
4794 | const char *errmsg = NULL((void *)0); | |||
4795 | struct carpreq carpr; | |||
4796 | int advbase; | |||
4797 | ||||
4798 | advbase = strtonum(val, 0, 254, &errmsg); | |||
4799 | if (errmsg) | |||
4800 | errx(1, "advbase %s: %s", val, errmsg); | |||
4801 | ||||
4802 | bzero(&carpr, sizeof(struct carpreq)); | |||
4803 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4804 | ||||
4805 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4806 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4807 | ||||
4808 | carpr.carpr_advbase = advbase; | |||
4809 | ||||
4810 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4811 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4812 | } | |||
4813 | ||||
4814 | void | |||
4815 | setcarppeer(const char *val, int d) | |||
4816 | { | |||
4817 | struct carpreq carpr; | |||
4818 | struct addrinfo hints, *peerres; | |||
4819 | int ecode; | |||
4820 | ||||
4821 | bzero(&carpr, sizeof(struct carpreq)); | |||
4822 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4823 | ||||
4824 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4825 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4826 | ||||
4827 | bzero(&hints, sizeof(hints)); | |||
4828 | hints.ai_family = AF_INET2; | |||
4829 | hints.ai_socktype = SOCK_DGRAM2; | |||
4830 | ||||
4831 | if ((ecode = getaddrinfo(val, NULL((void *)0), &hints, &peerres)) != 0) | |||
4832 | errx(1, "error in parsing address string: %s", | |||
4833 | gai_strerror(ecode)); | |||
4834 | ||||
4835 | if (peerres->ai_addr->sa_family != AF_INET2) | |||
4836 | errx(1, "only IPv4 addresses supported for the carppeer"); | |||
4837 | ||||
4838 | carpr.carpr_peer.s_addr = ((struct sockaddr_in *) | |||
4839 | peerres->ai_addr)->sin_addr.s_addr; | |||
4840 | ||||
4841 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4842 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4843 | ||||
4844 | freeaddrinfo(peerres); | |||
4845 | } | |||
4846 | ||||
4847 | void | |||
4848 | unsetcarppeer(const char *val, int d) | |||
4849 | { | |||
4850 | struct carpreq carpr; | |||
4851 | ||||
4852 | bzero(&carpr, sizeof(struct carpreq)); | |||
4853 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4854 | ||||
4855 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4856 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4857 | ||||
4858 | bzero(&carpr.carpr_peer, sizeof(carpr.carpr_peer)); | |||
4859 | ||||
4860 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4861 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4862 | } | |||
4863 | ||||
4864 | void | |||
4865 | setcarp_state(const char *val, int d) | |||
4866 | { | |||
4867 | struct carpreq carpr; | |||
4868 | int i; | |||
4869 | ||||
4870 | bzero(&carpr, sizeof(struct carpreq)); | |||
4871 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4872 | ||||
4873 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4874 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4875 | ||||
4876 | for (i = 0; i <= CARP_MAXSTATE2; i++) { | |||
4877 | if (!strcasecmp(val, carp_states[i])) { | |||
4878 | carpr.carpr_state = i; | |||
4879 | break; | |||
4880 | } | |||
4881 | } | |||
4882 | ||||
4883 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4884 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4885 | } | |||
4886 | ||||
4887 | void | |||
4888 | setcarpdev(const char *val, int d) | |||
4889 | { | |||
4890 | struct carpreq carpr; | |||
4891 | ||||
4892 | bzero(&carpr, sizeof(struct carpreq)); | |||
4893 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4894 | ||||
4895 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4896 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4897 | ||||
4898 | strlcpy(carpr.carpr_carpdev, val, sizeof(carpr.carpr_carpdev)); | |||
4899 | ||||
4900 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4901 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4902 | } | |||
4903 | ||||
4904 | void | |||
4905 | setcarp_nodes(const char *val, int d) | |||
4906 | { | |||
4907 | char *optlist, *str; | |||
4908 | int i; | |||
4909 | struct carpreq carpr; | |||
4910 | ||||
4911 | bzero(&carpr, sizeof(struct carpreq)); | |||
4912 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4913 | ||||
4914 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4915 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4916 | ||||
4917 | bzero(carpr.carpr_vhids, sizeof(carpr.carpr_vhids)); | |||
4918 | bzero(carpr.carpr_advskews, sizeof(carpr.carpr_advskews)); | |||
4919 | ||||
4920 | optlist = strdup(val); | |||
4921 | if (optlist == NULL((void *)0)) | |||
4922 | err(1, "strdup"); | |||
4923 | ||||
4924 | str = strtok(optlist, ","); | |||
4925 | for (i = 0; str != NULL((void *)0); i++) { | |||
4926 | u_int vhid, advskew; | |||
4927 | ||||
4928 | if (i >= CARP_MAXNODES32) | |||
4929 | errx(1, "too many carp nodes"); | |||
4930 | if (sscanf(str, "%u:%u", &vhid, &advskew) != 2) { | |||
4931 | errx(1, "non parsable arg: %s", str); | |||
4932 | } | |||
4933 | if (vhid > 255) | |||
4934 | errx(1, "vhid %u: value too large", vhid); | |||
4935 | if (advskew >= 255) | |||
4936 | errx(1, "advskew %u: value too large", advskew); | |||
4937 | ||||
4938 | carpr.carpr_vhids[i] = vhid; | |||
4939 | carpr.carpr_advskews[i] = advskew; | |||
4940 | str = strtok(NULL((void *)0), ","); | |||
4941 | } | |||
4942 | free(optlist); | |||
4943 | ||||
4944 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4945 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4946 | } | |||
4947 | ||||
4948 | void | |||
4949 | setcarp_balancing(const char *val, int d) | |||
4950 | { | |||
4951 | int i; | |||
4952 | struct carpreq carpr; | |||
4953 | ||||
4954 | bzero(&carpr, sizeof(struct carpreq)); | |||
4955 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&carpr; | |||
4956 | ||||
4957 | if (ioctl(sock, SIOCGVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((246))), (caddr_t)&ifr) == -1) | |||
4958 | err(1, "%s: SIOCGVH", ifr.ifr_name); | |||
4959 | ||||
4960 | for (i = 0; i <= CARP_BAL_MAXID3; i++) | |||
4961 | if (!strcasecmp(val, carp_bal_modes[i])) | |||
4962 | break; | |||
4963 | ||||
4964 | if (i > CARP_BAL_MAXID3) | |||
4965 | errx(1, "balancing %s: unknown mode", val); | |||
4966 | ||||
4967 | carpr.carpr_balancing = i; | |||
4968 | ||||
4969 | if (ioctl(sock, SIOCSVH(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((245))), (caddr_t)&ifr) == -1) | |||
4970 | err(1, "%s: SIOCSVH", ifr.ifr_name); | |||
4971 | } | |||
4972 | ||||
4973 | void | |||
4974 | setpfsync_syncdev(const char *val, int d) | |||
4975 | { | |||
4976 | struct pfsyncreq preq; | |||
4977 | ||||
4978 | bzero(&preq, sizeof(struct pfsyncreq)); | |||
4979 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
4980 | ||||
4981 | if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((248))), (caddr_t)&ifr) == -1) | |||
4982 | err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); | |||
4983 | ||||
4984 | strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev)); | |||
4985 | ||||
4986 | if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((247))), (caddr_t)&ifr) == -1) | |||
4987 | err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); | |||
4988 | } | |||
4989 | ||||
4990 | void | |||
4991 | unsetpfsync_syncdev(const char *val, int d) | |||
4992 | { | |||
4993 | struct pfsyncreq preq; | |||
4994 | ||||
4995 | bzero(&preq, sizeof(struct pfsyncreq)); | |||
4996 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
4997 | ||||
4998 | if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((248))), (caddr_t)&ifr) == -1) | |||
4999 | err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); | |||
5000 | ||||
5001 | bzero(&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev)); | |||
5002 | ||||
5003 | if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((247))), (caddr_t)&ifr) == -1) | |||
5004 | err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); | |||
5005 | } | |||
5006 | ||||
5007 | void | |||
5008 | setpfsync_syncpeer(const char *val, int d) | |||
5009 | { | |||
5010 | struct pfsyncreq preq; | |||
5011 | struct addrinfo hints, *peerres; | |||
5012 | int ecode; | |||
5013 | ||||
5014 | bzero(&preq, sizeof(struct pfsyncreq)); | |||
5015 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5016 | ||||
5017 | if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((248))), (caddr_t)&ifr) == -1) | |||
5018 | err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); | |||
5019 | ||||
5020 | memset(&hints, 0, sizeof(hints)); | |||
5021 | hints.ai_family = AF_INET2; | |||
5022 | hints.ai_socktype = SOCK_DGRAM2; /*dummy*/ | |||
5023 | ||||
5024 | if ((ecode = getaddrinfo(val, NULL((void *)0), &hints, &peerres)) != 0) | |||
5025 | errx(1, "error in parsing address string: %s", | |||
5026 | gai_strerror(ecode)); | |||
5027 | ||||
5028 | if (peerres->ai_addr->sa_family != AF_INET2) | |||
5029 | errx(1, "only IPv4 addresses supported for the syncpeer"); | |||
5030 | ||||
5031 | preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *) | |||
5032 | peerres->ai_addr)->sin_addr.s_addr; | |||
5033 | ||||
5034 | if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((247))), (caddr_t)&ifr) == -1) | |||
5035 | err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); | |||
5036 | ||||
5037 | freeaddrinfo(peerres); | |||
5038 | } | |||
5039 | ||||
5040 | void | |||
5041 | unsetpfsync_syncpeer(const char *val, int d) | |||
5042 | { | |||
5043 | struct pfsyncreq preq; | |||
5044 | ||||
5045 | bzero(&preq, sizeof(struct pfsyncreq)); | |||
5046 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5047 | ||||
5048 | if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((248))), (caddr_t)&ifr) == -1) | |||
5049 | err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); | |||
5050 | ||||
5051 | preq.pfsyncr_syncpeer.s_addr = 0; | |||
5052 | ||||
5053 | if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((247))), (caddr_t)&ifr) == -1) | |||
5054 | err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); | |||
5055 | } | |||
5056 | ||||
5057 | void | |||
5058 | setpfsync_maxupd(const char *val, int d) | |||
5059 | { | |||
5060 | const char *errmsg = NULL((void *)0); | |||
5061 | struct pfsyncreq preq; | |||
5062 | int maxupdates; | |||
5063 | ||||
5064 | maxupdates = strtonum(val, 0, 255, &errmsg); | |||
5065 | if (errmsg) | |||
5066 | errx(1, "maxupd %s: %s", val, errmsg); | |||
5067 | ||||
5068 | bzero(&preq, sizeof(struct pfsyncreq)); | |||
5069 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5070 | ||||
5071 | if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((248))), (caddr_t)&ifr) == -1) | |||
5072 | err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); | |||
5073 | ||||
5074 | preq.pfsyncr_maxupdates = maxupdates; | |||
5075 | ||||
5076 | if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((247))), (caddr_t)&ifr) == -1) | |||
5077 | err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); | |||
5078 | } | |||
5079 | ||||
5080 | void | |||
5081 | setpfsync_defer(const char *val, int d) | |||
5082 | { | |||
5083 | struct pfsyncreq preq; | |||
5084 | ||||
5085 | bzero(&preq, sizeof(struct pfsyncreq)); | |||
5086 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5087 | ||||
5088 | if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((248))), (caddr_t)&ifr) == -1) | |||
5089 | err(1, "%s: SIOCGETPFSYNC", ifr.ifr_name); | |||
5090 | ||||
5091 | preq.pfsyncr_defer = d; | |||
5092 | if (ioctl(sock, SIOCSETPFSYNC((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((247))), (caddr_t)&ifr) == -1) | |||
5093 | err(1, "%s: SIOCSETPFSYNC", ifr.ifr_name); | |||
5094 | } | |||
5095 | ||||
5096 | void | |||
5097 | pfsync_status(void) | |||
5098 | { | |||
5099 | struct pfsyncreq preq; | |||
5100 | ||||
5101 | bzero(&preq, sizeof(struct pfsyncreq)); | |||
5102 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5103 | ||||
5104 | if (ioctl(sock, SIOCGETPFSYNC(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((248))), (caddr_t)&ifr) == -1) | |||
5105 | return; | |||
5106 | ||||
5107 | if (preq.pfsyncr_syncdev[0] != '\0') { | |||
5108 | printf("\tpfsync: syncdev: %s ", preq.pfsyncr_syncdev); | |||
5109 | if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0xe00000f0))) ? (__uint32_t)(((__uint32_t)(((u_int32_t)(0xe00000f0))) & 0xff ) << 24 | ((__uint32_t)(((u_int32_t)(0xe00000f0))) & 0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0xe00000f0)) ) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0xe00000f0 ))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)( 0xe00000f0))))) | |||
5110 | printf("syncpeer: %s ", | |||
5111 | inet_ntoa(preq.pfsyncr_syncpeer)); | |||
5112 | printf("maxupd: %d ", preq.pfsyncr_maxupdates); | |||
5113 | printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off"); | |||
5114 | } | |||
5115 | } | |||
5116 | ||||
5117 | void | |||
5118 | pflow_status(void) | |||
5119 | { | |||
5120 | struct pflowreq preq; | |||
5121 | struct sockaddr_in *sin; | |||
5122 | struct sockaddr_in6 *sin6; | |||
5123 | int error; | |||
5124 | char buf[INET6_ADDRSTRLEN46]; | |||
5125 | ||||
5126 | bzero(&preq, sizeof(struct pflowreq)); | |||
5127 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5128 | ||||
5129 | if (ioctl(sock, SIOCGETPFLOW(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((254))), (caddr_t)&ifr) == -1) | |||
5130 | return; | |||
5131 | ||||
5132 | if (preq.flowsrc.ss_family == AF_INET2 || preq.flowsrc.ss_family == | |||
5133 | AF_INET624) { | |||
5134 | error = getnameinfo((struct sockaddr*)&preq.flowsrc, | |||
5135 | preq.flowsrc.ss_len, buf, sizeof(buf), NULL((void *)0), 0, | |||
5136 | NI_NUMERICHOST1); | |||
5137 | if (error) | |||
5138 | err(1, "sender: %s", gai_strerror(error)); | |||
5139 | } | |||
5140 | ||||
5141 | printf("\tpflow: "); | |||
5142 | switch (preq.flowsrc.ss_family) { | |||
5143 | case AF_INET2: | |||
5144 | sin = (struct sockaddr_in*) &preq.flowsrc; | |||
5145 | if (sin->sin_addr.s_addr != INADDR_ANY((u_int32_t)(0x00000000))) { | |||
5146 | printf("sender: %s", buf); | |||
5147 | if (sin->sin_port != 0) | |||
5148 | printf(":%u", ntohs(sin->sin_port)(__uint16_t)(__builtin_constant_p(sin->sin_port) ? (__uint16_t )(((__uint16_t)(sin->sin_port) & 0xffU) << 8 | ( (__uint16_t)(sin->sin_port) & 0xff00U) >> 8) : __swap16md (sin->sin_port))); | |||
5149 | printf(" "); | |||
5150 | } | |||
5151 | break; | |||
5152 | case AF_INET624: | |||
5153 | sin6 = (struct sockaddr_in6*) &preq.flowsrc; | |||
5154 | if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr )->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr)->__u6_addr .__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8 ]) == 0) && (*(const u_int32_t *)(const void *)(& (&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0) )) { | |||
5155 | printf("sender: [%s]", buf); | |||
5156 | if (sin6->sin6_port != 0) | |||
5157 | printf(":%u", ntohs(sin6->sin6_port)(__uint16_t)(__builtin_constant_p(sin6->sin6_port) ? (__uint16_t )(((__uint16_t)(sin6->sin6_port) & 0xffU) << 8 | ((__uint16_t)(sin6->sin6_port) & 0xff00U) >> 8) : __swap16md(sin6->sin6_port))); | |||
5158 | printf(" "); | |||
5159 | } | |||
5160 | default: | |||
5161 | break; | |||
5162 | } | |||
5163 | if (preq.flowdst.ss_family == AF_INET2 || preq.flowdst.ss_family == | |||
5164 | AF_INET624) { | |||
5165 | error = getnameinfo((struct sockaddr*)&preq.flowdst, | |||
5166 | preq.flowdst.ss_len, buf, sizeof(buf), NULL((void *)0), 0, | |||
5167 | NI_NUMERICHOST1); | |||
5168 | if (error) | |||
5169 | err(1, "receiver: %s", gai_strerror(error)); | |||
5170 | } | |||
5171 | switch (preq.flowdst.ss_family) { | |||
5172 | case AF_INET2: | |||
5173 | sin = (struct sockaddr_in*)&preq.flowdst; | |||
5174 | printf("receiver: %s:", sin->sin_addr.s_addr != INADDR_ANY((u_int32_t)(0x00000000)) ? | |||
5175 | buf : "INVALID"); | |||
5176 | if (sin->sin_port == 0) | |||
5177 | printf("%s ", "INVALID"); | |||
5178 | else | |||
5179 | printf("%u ", ntohs(sin->sin_port)(__uint16_t)(__builtin_constant_p(sin->sin_port) ? (__uint16_t )(((__uint16_t)(sin->sin_port) & 0xffU) << 8 | ( (__uint16_t)(sin->sin_port) & 0xff00U) >> 8) : __swap16md (sin->sin_port))); | |||
5180 | break; | |||
5181 | case AF_INET624: | |||
5182 | sin6 = (struct sockaddr_in6*) &preq.flowdst; | |||
5183 | printf("receiver: [%s]:", | |||
5184 | !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr )->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr)->__u6_addr .__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8 ]) == 0) && (*(const u_int32_t *)(const void *)(& (&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0) ) ? buf : | |||
5185 | "INVALID"); | |||
5186 | if (sin6->sin6_port == 0) | |||
5187 | printf("%s ", "INVALID"); | |||
5188 | else | |||
5189 | printf("%u ", ntohs(sin6->sin6_port)(__uint16_t)(__builtin_constant_p(sin6->sin6_port) ? (__uint16_t )(((__uint16_t)(sin6->sin6_port) & 0xffU) << 8 | ((__uint16_t)(sin6->sin6_port) & 0xff00U) >> 8) : __swap16md(sin6->sin6_port))); | |||
5190 | break; | |||
5191 | default: | |||
5192 | printf("receiver: INVALID:INVALID "); | |||
5193 | break; | |||
5194 | } | |||
5195 | printf("version: %d\n", preq.version); | |||
5196 | } | |||
5197 | ||||
5198 | void | |||
5199 | pflow_addr(const char *val, struct sockaddr_storage *ss) { | |||
5200 | struct addrinfo hints, *res0; | |||
5201 | int error, flag; | |||
5202 | char *cp, *ip, *port, buf[HOST_NAME_MAX255+1 + sizeof (":65535")]; | |||
5203 | ||||
5204 | if (strlcpy(buf, val, sizeof(buf)) >= sizeof(buf)) | |||
5205 | errx(1, "%s bad value", val); | |||
5206 | ||||
5207 | port = NULL((void *)0); | |||
5208 | cp = buf; | |||
5209 | if (*cp == '[') | |||
5210 | flag = 1; | |||
5211 | else | |||
5212 | flag = 0; | |||
5213 | ||||
5214 | for(; *cp; ++cp) { | |||
5215 | if (*cp == ']' && *(cp + 1) == ':' && flag) { | |||
5216 | *cp = '\0'; | |||
5217 | *(cp + 1) = '\0'; | |||
5218 | port = cp + 2; | |||
5219 | break; | |||
5220 | } | |||
5221 | if (*cp == ']' && *(cp + 1) == '\0' && flag) { | |||
5222 | *cp = '\0'; | |||
5223 | port = NULL((void *)0); | |||
5224 | break; | |||
5225 | } | |||
5226 | if (*cp == ':' && !flag) { | |||
5227 | *cp = '\0'; | |||
5228 | port = cp + 1; | |||
5229 | break; | |||
5230 | } | |||
5231 | } | |||
5232 | ||||
5233 | ip = buf; | |||
5234 | if (flag) | |||
5235 | ip++; | |||
5236 | ||||
5237 | bzero(&hints, sizeof(hints)); | |||
5238 | hints.ai_family = AF_UNSPEC0; | |||
5239 | hints.ai_socktype = SOCK_DGRAM2; /*dummy*/ | |||
5240 | hints.ai_flags = AI_NUMERICHOST4; | |||
5241 | ||||
5242 | if ((error = getaddrinfo(ip, port, &hints, &res0)) != 0) | |||
5243 | errx(1, "error in parsing address string: %s", | |||
5244 | gai_strerror(error)); | |||
5245 | ||||
5246 | memcpy(ss, res0->ai_addr, res0->ai_addr->sa_len); | |||
5247 | freeaddrinfo(res0); | |||
5248 | } | |||
5249 | ||||
5250 | void | |||
5251 | setpflow_sender(const char *val, int d) | |||
5252 | { | |||
5253 | struct pflowreq preq; | |||
5254 | ||||
5255 | bzero(&preq, sizeof(struct pflowreq)); | |||
5256 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5257 | preq.addrmask |= PFLOW_MASK_SRCIP0x01; | |||
5258 | pflow_addr(val, &preq.flowsrc); | |||
5259 | ||||
5260 | if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((253))), (caddr_t)&ifr) == -1) | |||
5261 | err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); | |||
5262 | } | |||
5263 | ||||
5264 | void | |||
5265 | unsetpflow_sender(const char *val, int d) | |||
5266 | { | |||
5267 | struct pflowreq preq; | |||
5268 | ||||
5269 | bzero(&preq, sizeof(struct pflowreq)); | |||
5270 | preq.addrmask |= PFLOW_MASK_SRCIP0x01; | |||
5271 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5272 | if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((253))), (caddr_t)&ifr) == -1) | |||
5273 | err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); | |||
5274 | } | |||
5275 | ||||
5276 | void | |||
5277 | setpflow_receiver(const char *val, int d) | |||
5278 | { | |||
5279 | struct pflowreq preq; | |||
5280 | ||||
5281 | bzero(&preq, sizeof(struct pflowreq)); | |||
5282 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5283 | preq.addrmask |= PFLOW_MASK_DSTIP0x02; | |||
5284 | pflow_addr(val, &preq.flowdst); | |||
5285 | ||||
5286 | if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((253))), (caddr_t)&ifr) == -1) | |||
5287 | err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); | |||
5288 | } | |||
5289 | ||||
5290 | void | |||
5291 | unsetpflow_receiver(const char *val, int d) | |||
5292 | { | |||
5293 | struct pflowreq preq; | |||
5294 | ||||
5295 | bzero(&preq, sizeof(struct pflowreq)); | |||
5296 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5297 | preq.addrmask |= PFLOW_MASK_DSTIP0x02; | |||
5298 | if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((253))), (caddr_t)&ifr) == -1) | |||
5299 | err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); | |||
5300 | } | |||
5301 | ||||
5302 | /* PFLOWPROTO XXX */ | |||
5303 | void | |||
5304 | setpflowproto(const char *val, int d) | |||
5305 | { | |||
5306 | struct pflow_protos ppr[] = PFLOW_PROTOS{ { "5", 5 }, { "10", 10 }, }; | |||
5307 | struct pflowreq preq; | |||
5308 | int i; | |||
5309 | ||||
5310 | bzero(&preq, sizeof(preq)); | |||
5311 | preq.version = PFLOW_PROTO_MAX11; | |||
5312 | ||||
5313 | for (i = 0; i < (sizeof(ppr) / sizeof(ppr[0])); i++) { | |||
5314 | if (strcmp(val, ppr[i].ppr_name) == 0) { | |||
5315 | preq.version = ppr[i].ppr_proto; | |||
5316 | break; | |||
5317 | } | |||
5318 | } | |||
5319 | if (preq.version == PFLOW_PROTO_MAX11) | |||
5320 | errx(1, "Invalid pflow protocol: %s", val); | |||
5321 | ||||
5322 | preq.addrmask |= PFLOW_MASK_VERSION0x04; | |||
5323 | ||||
5324 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&preq; | |||
5325 | ||||
5326 | if (ioctl(sock, SIOCSETPFLOW((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((253))), (caddr_t)&ifr) == -1) | |||
5327 | err(1, "%s: SIOCSETPFLOW", ifr.ifr_name); | |||
5328 | } | |||
5329 | ||||
5330 | void | |||
5331 | pppoe_status(void) | |||
5332 | { | |||
5333 | struct pppoediscparms parms; | |||
5334 | struct pppoeconnectionstate state; | |||
5335 | ||||
5336 | memset(&state, 0, sizeof(state)); | |||
5337 | ||||
5338 | strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); | |||
5339 | if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pppoediscparms) & 0x1fff) << 16) | ((('i')) << 8) | ((111))), &parms) == -1) | |||
5340 | return; | |||
5341 | ||||
5342 | printf("\tdev: %s ", parms.eth_ifname); | |||
5343 | ||||
5344 | if (*parms.ac_name) | |||
5345 | printf("ac: %s ", parms.ac_name); | |||
5346 | if (*parms.service_name) | |||
5347 | printf("svc: %s ", parms.service_name); | |||
5348 | ||||
5349 | strlcpy(state.ifname, ifname, sizeof(state.ifname)); | |||
5350 | if (ioctl(sock, PPPOEGETSESSION(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pppoeconnectionstate) & 0x1fff) << 16) | (( ('i')) << 8) | ((112))), &state) == -1) | |||
5351 | err(1, "PPPOEGETSESSION"); | |||
5352 | ||||
5353 | printf("state: "); | |||
5354 | switch (state.state) { | |||
5355 | case PPPOE_STATE_INITIAL0: | |||
5356 | printf("initial"); break; | |||
5357 | case PPPOE_STATE_PADI_SENT1: | |||
5358 | printf("PADI sent"); break; | |||
5359 | case PPPOE_STATE_PADR_SENT2: | |||
5360 | printf("PADR sent"); break; | |||
5361 | case PPPOE_STATE_SESSION3: | |||
5362 | printf("session"); break; | |||
5363 | case PPPOE_STATE_CLOSING4: | |||
5364 | printf("closing"); break; | |||
5365 | } | |||
5366 | printf("\n\tsid: 0x%x", state.session_id); | |||
5367 | printf(" PADI retries: %d", state.padi_retry_no); | |||
5368 | printf(" PADR retries: %d", state.padr_retry_no); | |||
5369 | ||||
5370 | if (state.state == PPPOE_STATE_SESSION3) { | |||
5371 | struct timespec temp_time; | |||
5372 | time_t diff_time, day = 0; | |||
5373 | unsigned int hour = 0, min = 0, sec = 0; | |||
5374 | ||||
5375 | if (state.session_time.tv_sec != 0) { | |||
5376 | if (clock_gettime(CLOCK_BOOTTIME6, &temp_time) == -1) | |||
5377 | goto notime; | |||
5378 | diff_time = temp_time.tv_sec - | |||
5379 | state.session_time.tv_sec; | |||
5380 | ||||
5381 | day = diff_time / (60 * 60 * 24); | |||
5382 | diff_time %= (60 * 60 * 24); | |||
5383 | ||||
5384 | hour = diff_time / (60 * 60); | |||
5385 | diff_time %= (60 * 60); | |||
5386 | ||||
5387 | min = diff_time / 60; | |||
5388 | diff_time %= 60; | |||
5389 | ||||
5390 | sec = diff_time; | |||
5391 | } | |||
5392 | printf(" time: "); | |||
5393 | if (day != 0) | |||
5394 | printf("%lldd ", (long long)day); | |||
5395 | printf("%02u:%02u:%02u", hour, min, sec); | |||
5396 | } | |||
5397 | notime: | |||
5398 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
5399 | } | |||
5400 | ||||
5401 | void | |||
5402 | setpppoe_dev(const char *val, int d) | |||
5403 | { | |||
5404 | struct pppoediscparms parms; | |||
5405 | ||||
5406 | strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); | |||
5407 | if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pppoediscparms) & 0x1fff) << 16) | ((('i')) << 8) | ((111))), &parms) == -1) | |||
5408 | return; | |||
5409 | ||||
5410 | strlcpy(parms.eth_ifname, val, sizeof(parms.eth_ifname)); | |||
5411 | ||||
5412 | if (ioctl(sock, PPPOESETPARMS((unsigned long)0x80000000 | ((sizeof(struct pppoediscparms) & 0x1fff) << 16) | ((('i')) << 8) | ((110))), &parms) == -1) | |||
5413 | err(1, "PPPOESETPARMS"); | |||
5414 | } | |||
5415 | ||||
5416 | void | |||
5417 | setpppoe_svc(const char *val, int d) | |||
5418 | { | |||
5419 | struct pppoediscparms parms; | |||
5420 | ||||
5421 | strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); | |||
5422 | if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pppoediscparms) & 0x1fff) << 16) | ((('i')) << 8) | ((111))), &parms) == -1) | |||
5423 | return; | |||
5424 | ||||
5425 | if (d == 0) | |||
5426 | strlcpy(parms.service_name, val, sizeof(parms.service_name)); | |||
5427 | else | |||
5428 | memset(parms.service_name, 0, sizeof(parms.service_name)); | |||
5429 | ||||
5430 | if (ioctl(sock, PPPOESETPARMS((unsigned long)0x80000000 | ((sizeof(struct pppoediscparms) & 0x1fff) << 16) | ((('i')) << 8) | ((110))), &parms) == -1) | |||
5431 | err(1, "PPPOESETPARMS"); | |||
5432 | } | |||
5433 | ||||
5434 | void | |||
5435 | setpppoe_ac(const char *val, int d) | |||
5436 | { | |||
5437 | struct pppoediscparms parms; | |||
5438 | ||||
5439 | strlcpy(parms.ifname, ifname, sizeof(parms.ifname)); | |||
5440 | if (ioctl(sock, PPPOEGETPARMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pppoediscparms) & 0x1fff) << 16) | ((('i')) << 8) | ((111))), &parms) == -1) | |||
5441 | return; | |||
5442 | ||||
5443 | if (d == 0) | |||
5444 | strlcpy(parms.ac_name, val, sizeof(parms.ac_name)); | |||
5445 | else | |||
5446 | memset(parms.ac_name, 0, sizeof(parms.ac_name)); | |||
5447 | ||||
5448 | if (ioctl(sock, PPPOESETPARMS((unsigned long)0x80000000 | ((sizeof(struct pppoediscparms) & 0x1fff) << 16) | ((('i')) << 8) | ((110))), &parms) == -1) | |||
5449 | err(1, "PPPOESETPARMS"); | |||
5450 | } | |||
5451 | ||||
5452 | void | |||
5453 | spppauthinfo(struct sauthreq *spa, int d) | |||
5454 | { | |||
5455 | bzero(spa, sizeof(struct sauthreq)); | |||
5456 | ||||
5457 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)spa; | |||
5458 | spa->cmd = d == 0 ? SPPPIOGMAUTH((int)(('S' << 24) + (3 << 16) + sizeof(struct sauthreq ))) : SPPPIOGHAUTH((int)(('S' << 24) + (5 << 16) + sizeof(struct sauthreq ))); | |||
5459 | if (ioctl(sock, SIOCGSPPPPARAMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((148))), &ifr) == -1) | |||
5460 | err(1, "%s: SIOCGSPPPPARAMS(SPPPIOGXAUTH)", ifr.ifr_name); | |||
5461 | } | |||
5462 | ||||
5463 | void | |||
5464 | spppdnsinfo(struct sdnsreq *spd) | |||
5465 | { | |||
5466 | memset(spd, 0, sizeof(*spd)); | |||
5467 | ||||
5468 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)spd; | |||
5469 | spd->cmd = SPPPIOGDNS((int)(('S' << 24) + (7 << 16) + sizeof(struct sdnsreq ))); | |||
5470 | if (ioctl(sock, SIOCGSPPPPARAMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((148))), &ifr) == -1) | |||
5471 | err(1, "%s: SIOCGSPPPPARAMS(SPPPIOGDNS)", ifr.ifr_name); | |||
5472 | } | |||
5473 | ||||
5474 | void | |||
5475 | setspppproto(const char *val, int d) | |||
5476 | { | |||
5477 | struct sauthreq spa; | |||
5478 | ||||
5479 | spppauthinfo(&spa, d); | |||
5480 | ||||
5481 | if (strcmp(val, "pap") == 0) | |||
5482 | spa.proto = PPP_PAP0xc023; | |||
5483 | else if (strcmp(val, "chap") == 0) | |||
5484 | spa.proto = PPP_CHAP0xc223; | |||
5485 | else if (strcmp(val, "none") == 0) | |||
5486 | spa.proto = 0; | |||
5487 | else | |||
5488 | errx(1, "setpppproto"); | |||
5489 | ||||
5490 | spa.cmd = d == 0 ? SPPPIOSMAUTH((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq ))) : SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq ))); | |||
5491 | if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((147))), &ifr) == -1) | |||
5492 | err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); | |||
5493 | } | |||
5494 | ||||
5495 | void | |||
5496 | setsppppeerproto(const char *val, int d) | |||
5497 | { | |||
5498 | setspppproto(val, 1); | |||
5499 | } | |||
5500 | ||||
5501 | void | |||
5502 | setspppname(const char *val, int d) | |||
5503 | { | |||
5504 | struct sauthreq spa; | |||
5505 | ||||
5506 | spppauthinfo(&spa, d); | |||
5507 | ||||
5508 | if (spa.proto == 0) | |||
5509 | errx(1, "unspecified protocol"); | |||
5510 | if (strlcpy(spa.name, val, sizeof(spa.name)) >= sizeof(spa.name)) | |||
5511 | errx(1, "setspppname"); | |||
5512 | ||||
5513 | spa.cmd = d == 0 ? SPPPIOSMAUTH((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq ))) : SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq ))); | |||
5514 | if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((147))), &ifr) == -1) | |||
5515 | err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); | |||
5516 | } | |||
5517 | ||||
5518 | void | |||
5519 | setsppppeername(const char *val, int d) | |||
5520 | { | |||
5521 | setspppname(val, 1); | |||
5522 | } | |||
5523 | ||||
5524 | void | |||
5525 | setspppkey(const char *val, int d) | |||
5526 | { | |||
5527 | struct sauthreq spa; | |||
5528 | ||||
5529 | spppauthinfo(&spa, d); | |||
5530 | ||||
5531 | if (spa.proto == 0) | |||
5532 | errx(1, "unspecified protocol"); | |||
5533 | if (strlcpy(spa.secret, val, sizeof(spa.secret)) >= sizeof(spa.secret)) | |||
5534 | errx(1, "setspppkey"); | |||
5535 | ||||
5536 | spa.cmd = d == 0 ? SPPPIOSMAUTH((int)(('S' << 24) + (4 << 16) + sizeof(struct sauthreq ))) : SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq ))); | |||
5537 | if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((147))), &ifr) == -1) | |||
5538 | err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); | |||
5539 | } | |||
5540 | ||||
5541 | void | |||
5542 | setsppppeerkey(const char *val, int d) | |||
5543 | { | |||
5544 | setspppkey(val, 1); | |||
5545 | } | |||
5546 | ||||
5547 | void | |||
5548 | setsppppeerflag(const char *val, int d) | |||
5549 | { | |||
5550 | struct sauthreq spa; | |||
5551 | int flag; | |||
5552 | ||||
5553 | spppauthinfo(&spa, 1); | |||
5554 | ||||
5555 | if (spa.proto == 0) | |||
5556 | errx(1, "unspecified protocol"); | |||
5557 | if (strcmp(val, "callin") == 0) | |||
5558 | flag = AUTHFLAG_NOCALLOUT1; | |||
5559 | else if (strcmp(val, "norechallenge") == 0) | |||
5560 | flag = AUTHFLAG_NORECHALLENGE2; | |||
5561 | else | |||
5562 | errx(1, "setppppeerflags"); | |||
5563 | ||||
5564 | if (d) | |||
5565 | spa.flags &= ~flag; | |||
5566 | else | |||
5567 | spa.flags |= flag; | |||
5568 | ||||
5569 | spa.cmd = SPPPIOSHAUTH((int)(('S' << 24) + (6 << 16) + sizeof(struct sauthreq ))); | |||
5570 | if (ioctl(sock, SIOCSSPPPPARAMS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((147))), &ifr) == -1) | |||
5571 | err(1, "%s: SIOCSSPPPPARAMS(SPPPIOSXAUTH)", ifr.ifr_name); | |||
5572 | } | |||
5573 | ||||
5574 | void | |||
5575 | unsetsppppeerflag(const char *val, int d) | |||
5576 | { | |||
5577 | setsppppeerflag(val, 1); | |||
5578 | } | |||
5579 | ||||
5580 | void | |||
5581 | sppp_printproto(const char *name, struct sauthreq *auth) | |||
5582 | { | |||
5583 | if (auth->proto == 0) | |||
5584 | return; | |||
5585 | printf("%sproto ", name); | |||
5586 | switch (auth->proto) { | |||
5587 | case PPP_PAP0xc023: | |||
5588 | printf("pap "); | |||
5589 | break; | |||
5590 | case PPP_CHAP0xc223: | |||
5591 | printf("chap "); | |||
5592 | break; | |||
5593 | default: | |||
5594 | printf("0x%04x ", auth->proto); | |||
5595 | break; | |||
5596 | } | |||
5597 | if (auth->name[0]) | |||
5598 | printf("%sname \"%s\" ", name, auth->name); | |||
5599 | if (auth->secret[0]) | |||
5600 | printf("%skey \"%s\" ", name, auth->secret); | |||
5601 | } | |||
5602 | ||||
5603 | void | |||
5604 | sppp_status(void) | |||
5605 | { | |||
5606 | struct spppreq spr; | |||
5607 | struct sauthreq spa; | |||
5608 | struct sdnsreq spd; | |||
5609 | char astr[INET_ADDRSTRLEN16]; | |||
5610 | int i, n; | |||
5611 | ||||
5612 | bzero(&spr, sizeof(spr)); | |||
5613 | ||||
5614 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&spr; | |||
5615 | spr.cmd = SPPPIOGDEFS((int)(('S' << 24) + (1 << 16) + sizeof(struct spppreq ))); | |||
5616 | if (ioctl(sock, SIOCGSPPPPARAMS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((148))), &ifr) == -1) { | |||
5617 | return; | |||
5618 | } | |||
5619 | ||||
5620 | if (spr.phase == PHASE_DEAD) | |||
5621 | return; | |||
5622 | printf("\tsppp: phase "); | |||
5623 | switch (spr.phase) { | |||
5624 | case PHASE_ESTABLISH: | |||
5625 | printf("establish "); | |||
5626 | break; | |||
5627 | case PHASE_TERMINATE: | |||
5628 | printf("terminate "); | |||
5629 | break; | |||
5630 | case PHASE_AUTHENTICATE: | |||
5631 | printf("authenticate "); | |||
5632 | break; | |||
5633 | case PHASE_NETWORK: | |||
5634 | printf("network "); | |||
5635 | break; | |||
5636 | default: | |||
5637 | printf("illegal "); | |||
5638 | break; | |||
5639 | } | |||
5640 | ||||
5641 | spppauthinfo(&spa, 0); | |||
5642 | sppp_printproto("auth", &spa); | |||
5643 | spppauthinfo(&spa, 1); | |||
5644 | sppp_printproto("peer", &spa); | |||
5645 | if (spa.flags & AUTHFLAG_NOCALLOUT1) | |||
5646 | printf("callin "); | |||
5647 | if (spa.flags & AUTHFLAG_NORECHALLENGE2) | |||
5648 | printf("norechallenge "); | |||
5649 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
5650 | ||||
5651 | spppdnsinfo(&spd); | |||
5652 | for (i = 0, n = 0; i < IPCP_MAX_DNSSRV2; i++) { | |||
5653 | if (spd.dns[i].s_addr == INADDR_ANY((u_int32_t)(0x00000000))) | |||
5654 | break; | |||
5655 | printf("%s %s", n++ ? "" : "\tdns:", | |||
5656 | inet_ntop(AF_INET2, &spd.dns[i], astr, sizeof(astr))); | |||
5657 | } | |||
5658 | if (n) | |||
5659 | printf("\n"); | |||
5660 | } | |||
5661 | ||||
5662 | void | |||
5663 | setkeepalive(const char *timeout, const char *count) | |||
5664 | { | |||
5665 | const char *errmsg = NULL((void *)0); | |||
5666 | struct ifkalivereq ikar; | |||
5667 | int t, c; | |||
5668 | ||||
5669 | t = strtonum(timeout, 1, 3600, &errmsg); | |||
5670 | if (errmsg) | |||
5671 | errx(1, "keepalive period %s: %s", timeout, errmsg); | |||
5672 | c = strtonum(count, 2, 600, &errmsg); | |||
5673 | if (errmsg) | |||
5674 | errx(1, "keepalive count %s: %s", count, errmsg); | |||
5675 | ||||
5676 | strlcpy(ikar.ikar_name, ifname, sizeof(ikar.ikar_name)); | |||
5677 | ikar.ikar_timeo = t; | |||
5678 | ikar.ikar_cnt = c; | |||
5679 | if (ioctl(sock, SIOCSETKALIVE((unsigned long)0x80000000 | ((sizeof(struct ifkalivereq) & 0x1fff) << 16) | ((('i')) << 8) | ((163))), (caddr_t)&ikar) == -1) | |||
5680 | warn("SIOCSETKALIVE"); | |||
5681 | } | |||
5682 | ||||
5683 | void | |||
5684 | unsetkeepalive(const char *val, int d) | |||
5685 | { | |||
5686 | struct ifkalivereq ikar; | |||
5687 | ||||
5688 | bzero(&ikar, sizeof(ikar)); | |||
5689 | strlcpy(ikar.ikar_name, ifname, sizeof(ikar.ikar_name)); | |||
5690 | if (ioctl(sock, SIOCSETKALIVE((unsigned long)0x80000000 | ((sizeof(struct ifkalivereq) & 0x1fff) << 16) | ((('i')) << 8) | ((163))), (caddr_t)&ikar) == -1) | |||
5691 | warn("SIOCSETKALIVE"); | |||
5692 | } | |||
5693 | ||||
5694 | void | |||
5695 | setifpriority(const char *id, int param) | |||
5696 | { | |||
5697 | const char *errmsg = NULL((void *)0); | |||
5698 | int prio; | |||
5699 | ||||
5700 | prio = strtonum(id, 0, 15, &errmsg); | |||
5701 | if (errmsg) | |||
5702 | errx(1, "priority %s: %s", id, errmsg); | |||
5703 | ||||
5704 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
5705 | ifr.ifr_metricifr_ifru.ifru_metric = prio; | |||
5706 | if (ioctl(sock, SIOCSIFPRIORITY((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((155))), (caddr_t)&ifr) == -1) | |||
5707 | warn("SIOCSIFPRIORITY"); | |||
5708 | } | |||
5709 | ||||
5710 | /* | |||
5711 | * WireGuard configuration | |||
5712 | * | |||
5713 | * WG_BASE64_KEY_LEN specifies the size of a base64 encoded WireGuard key. | |||
5714 | * WG_TMP_KEY_LEN specifies the size of a decoded base64 key. For every 4 | |||
5715 | * input (base64) bytes, 3 output bytes wil be produced. The output will be | |||
5716 | * padded with 0 bits, therefore we need more than the regular 32 bytes of | |||
5717 | * space. | |||
5718 | */ | |||
5719 | #define WG_BASE64_KEY_LEN(4 * ((32 + 2) / 3)) (4 * ((WG_KEY_LEN32 + 2) / 3)) | |||
5720 | #define WG_LOAD_KEY(dst, src, fn_name)do { uint8_t _tmp[32]; int _r; if (strlen(src) != (4 * ((32 + 2) / 3))) errx(1, fn_name " (key): invalid length"); if ((_r = __b64_pton(src, _tmp, sizeof(_tmp))) != sizeof(_tmp)) errx (1, fn_name " (key): invalid base64 %d/%zu", _r, sizeof(_tmp) ); memcpy(dst, _tmp, 32); } while (0) do { \ | |||
5721 | uint8_t _tmp[WG_KEY_LEN32]; int _r; \ | |||
5722 | if (strlen(src) != WG_BASE64_KEY_LEN(4 * ((32 + 2) / 3))) \ | |||
5723 | errx(1, fn_name " (key): invalid length"); \ | |||
5724 | if ((_r = b64_pton__b64_pton(src, _tmp, sizeof(_tmp))) != sizeof(_tmp)) \ | |||
5725 | errx(1, fn_name " (key): invalid base64 %d/%zu", _r, sizeof(_tmp)); \ | |||
5726 | memcpy(dst, _tmp, WG_KEY_LEN32); \ | |||
5727 | } while (0) | |||
5728 | ||||
5729 | struct wg_data_io wgdata = { 0 }; | |||
5730 | struct wg_interface_io *wg_interface = NULL((void *)0); | |||
5731 | struct wg_peer_io *wg_peer = NULL((void *)0); | |||
5732 | struct wg_aip_io *wg_aip = NULL((void *)0); | |||
5733 | ||||
5734 | void | |||
5735 | ensurewginterface(void) | |||
5736 | { | |||
5737 | if (wg_interface != NULL((void *)0)) | |||
5738 | return; | |||
5739 | wgdata.wgd_size = sizeof(*wg_interface); | |||
5740 | wgdata.wgd_interface = wg_interface = calloc(1, wgdata.wgd_size); | |||
5741 | if (wg_interface == NULL((void *)0)) | |||
5742 | err(1, "calloc"); | |||
5743 | } | |||
5744 | ||||
5745 | void | |||
5746 | growwgdata(size_t by) | |||
5747 | { | |||
5748 | ptrdiff_t peer_offset, aip_offset; | |||
5749 | ||||
5750 | if (wg_interface == NULL((void *)0)) | |||
5751 | wgdata.wgd_size = sizeof(*wg_interface); | |||
5752 | ||||
5753 | peer_offset = (void *)wg_peer - (void *)wg_interface; | |||
5754 | aip_offset = (void *)wg_aip - (void *)wg_interface; | |||
5755 | ||||
5756 | wgdata.wgd_size += by; | |||
5757 | wgdata.wgd_interface = realloc(wg_interface, wgdata.wgd_size); | |||
5758 | if (wgdata.wgd_interface == NULL((void *)0)) | |||
5759 | err(1, "calloc"); | |||
5760 | if (wg_interface == NULL((void *)0)) | |||
5761 | bzero(wgdata.wgd_interface, sizeof(*wg_interface)); | |||
5762 | wg_interface = wgdata.wgd_interface; | |||
5763 | ||||
5764 | if (wg_peer != NULL((void *)0)) | |||
5765 | wg_peer = (void *)wg_interface + peer_offset; | |||
5766 | if (wg_aip != NULL((void *)0)) | |||
5767 | wg_aip = (void *)wg_interface + aip_offset; | |||
5768 | ||||
5769 | bzero((char *)wg_interface + wgdata.wgd_size - by, by); | |||
5770 | } | |||
5771 | ||||
5772 | void | |||
5773 | setwgpeer(const char *peerkey_b64, int param) | |||
5774 | { | |||
5775 | growwgdata(sizeof(*wg_peer)); | |||
5776 | if (wg_aip) | |||
5777 | wg_peer = (struct wg_peer_io *)wg_aip; | |||
5778 | else | |||
5779 | wg_peer = &wg_interface->i_peers[0]; | |||
5780 | wg_aip = &wg_peer->p_aips[0]; | |||
5781 | wg_peer->p_flags |= WG_PEER_HAS_PUBLIC(1 << 0); | |||
5782 | WG_LOAD_KEY(wg_peer->p_public, peerkey_b64, "wgpeer")do { uint8_t _tmp[32]; int _r; if (strlen(peerkey_b64) != (4 * ((32 + 2) / 3))) errx(1, "wgpeer" " (key): invalid length"); if ((_r = __b64_pton(peerkey_b64, _tmp, sizeof(_tmp))) != sizeof (_tmp)) errx(1, "wgpeer" " (key): invalid base64 %d/%zu", _r, sizeof(_tmp)); memcpy(wg_peer->p_public, _tmp, 32); } while (0); | |||
5783 | wg_interface->i_peers_count++; | |||
5784 | } | |||
5785 | ||||
5786 | void | |||
5787 | setwgpeerdesc(const char *descr, int param) | |||
5788 | { | |||
5789 | if (wg_peer == NULL((void *)0)) | |||
5790 | errx(1, "wgdescr: wgpeer not set"); | |||
5791 | wg_peer->p_flags |= WG_PEER_SET_DESCRIPTION(1 << 7); | |||
5792 | strlcpy(wg_peer->p_description, descr, IFDESCRSIZE64); | |||
5793 | } | |||
5794 | ||||
5795 | void | |||
5796 | setwgpeeraip(const char *aip, int param) | |||
5797 | { | |||
5798 | int res; | |||
5799 | if (wg_peer == NULL((void *)0)) | |||
5800 | errx(1, "wgaip: wgpeer not set"); | |||
5801 | ||||
5802 | growwgdata(sizeof(*wg_aip)); | |||
5803 | ||||
5804 | if ((res = inet_net_pton(AF_INET2, aip, &wg_aip->a_ipv4a_addr.addr_ipv4, | |||
5805 | sizeof(wg_aip->a_ipv4a_addr.addr_ipv4))) != -1) { | |||
5806 | wg_aip->a_af = AF_INET2; | |||
5807 | } else if ((res = inet_net_pton(AF_INET624, aip, &wg_aip->a_ipv6a_addr.addr_ipv6, | |||
5808 | sizeof(wg_aip->a_ipv6a_addr.addr_ipv6))) != -1) { | |||
5809 | wg_aip->a_af = AF_INET624; | |||
5810 | } else { | |||
5811 | errx(1, "wgaip: bad address"); | |||
5812 | } | |||
5813 | ||||
5814 | wg_aip->a_cidr = res; | |||
5815 | ||||
5816 | wg_peer->p_flags |= WG_PEER_REPLACE_AIPS(1 << 4); | |||
5817 | wg_peer->p_aips_count++; | |||
5818 | ||||
5819 | wg_aip++; | |||
5820 | } | |||
5821 | ||||
5822 | void | |||
5823 | setwgpeerep(const char *host, const char *service) | |||
5824 | { | |||
5825 | int error; | |||
5826 | struct addrinfo *ai; | |||
5827 | ||||
5828 | if (wg_peer == NULL((void *)0)) | |||
5829 | errx(1, "wgendpoint: wgpeer not set"); | |||
5830 | ||||
5831 | if ((error = getaddrinfo(host, service, NULL((void *)0), &ai)) != 0) | |||
5832 | errx(1, "%s", gai_strerror(error)); | |||
5833 | ||||
5834 | wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT(1 << 3); | |||
5835 | memcpy(&wg_peer->p_sap_endpoint.sa_sa, ai->ai_addr, ai->ai_addrlen); | |||
5836 | freeaddrinfo(ai); | |||
5837 | } | |||
5838 | ||||
5839 | void | |||
5840 | setwgpeerpsk(const char *psk_b64, int param) | |||
5841 | { | |||
5842 | if (wg_peer == NULL((void *)0)) | |||
5843 | errx(1, "wgpsk: wgpeer not set"); | |||
5844 | wg_peer->p_flags |= WG_PEER_HAS_PSK(1 << 1); | |||
5845 | WG_LOAD_KEY(wg_peer->p_psk, psk_b64, "wgpsk")do { uint8_t _tmp[32]; int _r; if (strlen(psk_b64) != (4 * (( 32 + 2) / 3))) errx(1, "wgpsk" " (key): invalid length"); if ( (_r = __b64_pton(psk_b64, _tmp, sizeof(_tmp))) != sizeof(_tmp )) errx(1, "wgpsk" " (key): invalid base64 %d/%zu", _r, sizeof (_tmp)); memcpy(wg_peer->p_psk, _tmp, 32); } while (0); | |||
5846 | } | |||
5847 | ||||
5848 | void | |||
5849 | setwgpeerpka(const char *pka, int param) | |||
5850 | { | |||
5851 | const char *errmsg = NULL((void *)0); | |||
5852 | if (wg_peer == NULL((void *)0)) | |||
5853 | errx(1, "wgpka: wgpeer not set"); | |||
5854 | /* 43200 == 12h, reasonable for a 16 bit value */ | |||
5855 | wg_peer->p_flags |= WG_PEER_HAS_PKA(1 << 2); | |||
5856 | wg_peer->p_pka = strtonum(pka, 0, 43200, &errmsg); | |||
5857 | if (errmsg) | |||
5858 | errx(1, "wgpka: %s, %s", pka, errmsg); | |||
5859 | } | |||
5860 | ||||
5861 | void | |||
5862 | setwgport(const char *port, int param) | |||
5863 | { | |||
5864 | const char *errmsg = NULL((void *)0); | |||
5865 | ensurewginterface(); | |||
5866 | wg_interface->i_flags |= WG_INTERFACE_HAS_PORT(1 << 2); | |||
5867 | wg_interface->i_port = strtonum(port, 0, 65535, &errmsg); | |||
5868 | if (errmsg) | |||
5869 | errx(1, "wgport: %s, %s", port, errmsg); | |||
5870 | } | |||
5871 | ||||
5872 | void | |||
5873 | setwgkey(const char *private_b64, int param) | |||
5874 | { | |||
5875 | ensurewginterface(); | |||
5876 | wg_interface->i_flags |= WG_INTERFACE_HAS_PRIVATE(1 << 1); | |||
5877 | WG_LOAD_KEY(wg_interface->i_private, private_b64, "wgkey")do { uint8_t _tmp[32]; int _r; if (strlen(private_b64) != (4 * ((32 + 2) / 3))) errx(1, "wgkey" " (key): invalid length"); if ((_r = __b64_pton(private_b64, _tmp, sizeof(_tmp))) != sizeof (_tmp)) errx(1, "wgkey" " (key): invalid base64 %d/%zu", _r, sizeof (_tmp)); memcpy(wg_interface->i_private, _tmp, 32); } while (0); | |||
5878 | } | |||
5879 | ||||
5880 | void | |||
5881 | setwgrtable(const char *id, int param) | |||
5882 | { | |||
5883 | const char *errmsg = NULL((void *)0); | |||
5884 | ensurewginterface(); | |||
5885 | wg_interface->i_flags |= WG_INTERFACE_HAS_RTABLE(1 << 3); | |||
5886 | wg_interface->i_rtable = strtonum(id, 0, RT_TABLEID_MAX255, &errmsg); | |||
5887 | if (errmsg) | |||
5888 | errx(1, "wgrtable %s: %s", id, errmsg); | |||
5889 | } | |||
5890 | ||||
5891 | void | |||
5892 | unsetwgpeer(const char *peerkey_b64, int param) | |||
5893 | { | |||
5894 | setwgpeer(peerkey_b64, param); | |||
5895 | wg_peer->p_flags |= WG_PEER_REMOVE(1 << 5); | |||
5896 | } | |||
5897 | ||||
5898 | void | |||
5899 | unsetwgpeerdesc(const char *descr, int param) | |||
5900 | { | |||
5901 | if (wg_peer == NULL((void *)0)) | |||
5902 | errx(1, "wgdescr: wgpeer not set"); | |||
5903 | wg_peer->p_flags |= WG_PEER_SET_DESCRIPTION(1 << 7); | |||
5904 | strlcpy(wg_peer->p_description, "", IFDESCRSIZE64); | |||
5905 | } | |||
5906 | ||||
5907 | void | |||
5908 | unsetwgpeerpsk(const char *value, int param) | |||
5909 | { | |||
5910 | if (wg_peer == NULL((void *)0)) | |||
5911 | errx(1, "wgpsk: wgpeer not set"); | |||
5912 | wg_peer->p_flags |= WG_PEER_HAS_PSK(1 << 1); | |||
5913 | bzero(wg_peer->p_psk, WG_KEY_LEN32); | |||
5914 | } | |||
5915 | ||||
5916 | void | |||
5917 | unsetwgpeerall(const char *value, int param) | |||
5918 | { | |||
5919 | ensurewginterface(); | |||
5920 | wg_interface->i_flags |= WG_INTERFACE_REPLACE_PEERS(1 << 4); | |||
5921 | } | |||
5922 | ||||
5923 | void | |||
5924 | process_wg_commands(void) | |||
5925 | { | |||
5926 | if (actions & A_WIREGUARD0x0040) { | |||
5927 | strlcpy(wgdata.wgd_name, ifname, sizeof(wgdata.wgd_name)); | |||
5928 | ||||
5929 | if (ioctl(sock, SIOCSWG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct wg_data_io) & 0x1fff) << 16) | ((('i')) << 8) | ((210))), (caddr_t)&wgdata) == -1) | |||
5930 | err(1, "%s: SIOCSWG", wgdata.wgd_name); | |||
5931 | } | |||
5932 | } | |||
5933 | ||||
5934 | void | |||
5935 | wg_status(int ifaliases) | |||
5936 | { | |||
5937 | size_t i, j, last_size; | |||
5938 | struct timespec now; | |||
5939 | char hbuf[NI_MAXHOST256], sbuf[NI_MAXSERV32]; | |||
5940 | char key[WG_BASE64_KEY_LEN(4 * ((32 + 2) / 3)) + 1]; | |||
5941 | ||||
5942 | strlcpy(wgdata.wgd_name, ifname, sizeof(wgdata.wgd_name)); | |||
5943 | wgdata.wgd_size = 0; | |||
5944 | wgdata.wgd_interface = NULL((void *)0); | |||
5945 | for (last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) { | |||
5946 | if (ioctl(sock, SIOCGWG(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct wg_data_io) & 0x1fff) << 16) | ((('i')) << 8) | ((211))), (caddr_t)&wgdata) < 0) { | |||
5947 | if (errno(*__errno()) == ENOTTY25) | |||
5948 | goto out; | |||
5949 | err(1, "%s: SIOCGWG", wgdata.wgd_name); | |||
5950 | } | |||
5951 | if (last_size >= wgdata.wgd_size) | |||
5952 | break; | |||
5953 | wgdata.wgd_interface = realloc(wgdata.wgd_interface, | |||
5954 | wgdata.wgd_size); | |||
5955 | if (!wgdata.wgd_interface) | |||
5956 | err(1, "realloc"); | |||
5957 | } | |||
5958 | wg_interface = wgdata.wgd_interface; | |||
5959 | ||||
5960 | if (wg_interface->i_flags & WG_INTERFACE_HAS_PORT(1 << 2)) | |||
5961 | printf("\twgport %hu\n", wg_interface->i_port); | |||
5962 | if (wg_interface->i_flags & WG_INTERFACE_HAS_RTABLE(1 << 3)) | |||
5963 | printf("\twgrtable %d\n", wg_interface->i_rtable); | |||
5964 | if (wg_interface->i_flags & WG_INTERFACE_HAS_PUBLIC(1 << 0)) { | |||
5965 | b64_ntop__b64_ntop(wg_interface->i_public, WG_KEY_LEN32, | |||
5966 | key, sizeof(key)); | |||
5967 | printf("\twgpubkey %s\n", key); | |||
5968 | } | |||
5969 | ||||
5970 | if (ifaliases) { | |||
5971 | wg_peer = &wg_interface->i_peers[0]; | |||
5972 | for (i = 0; i < wg_interface->i_peers_count; i++) { | |||
5973 | b64_ntop__b64_ntop(wg_peer->p_public, WG_KEY_LEN32, | |||
5974 | key, sizeof(key)); | |||
5975 | printf("\twgpeer %s\n", key); | |||
5976 | ||||
5977 | if (strlen(wg_peer->p_description)) | |||
5978 | printf("\t\twgdescr: %s\n", | |||
5979 | wg_peer->p_description); | |||
5980 | ||||
5981 | if (wg_peer->p_flags & WG_PEER_HAS_PSK(1 << 1)) | |||
5982 | printf("\t\twgpsk (present)\n"); | |||
5983 | ||||
5984 | if (wg_peer->p_flags & WG_PEER_HAS_PKA(1 << 2) && wg_peer->p_pka) | |||
5985 | printf("\t\twgpka %u (sec)\n", wg_peer->p_pka); | |||
5986 | ||||
5987 | if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT(1 << 3)) { | |||
5988 | if (getnameinfo(&wg_peer->p_sap_endpoint.sa_sa, wg_peer->p_sap_endpoint.sa_sa.sa_len, | |||
5989 | hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), | |||
5990 | NI_NUMERICHOST1 | NI_NUMERICSERV2) == 0) | |||
5991 | printf("\t\twgendpoint %s %s\n", hbuf, sbuf); | |||
5992 | else | |||
5993 | printf("\t\twgendpoint unable to print\n"); | |||
5994 | } | |||
5995 | ||||
5996 | printf("\t\ttx: %llu, rx: %llu\n", | |||
5997 | wg_peer->p_txbytes, wg_peer->p_rxbytes); | |||
5998 | ||||
5999 | if (wg_peer->p_last_handshake.tv_sec != 0) { | |||
6000 | clock_gettime(CLOCK_REALTIME0, &now); | |||
6001 | printf("\t\tlast handshake: %lld seconds ago\n", | |||
6002 | now.tv_sec - wg_peer->p_last_handshake.tv_sec); | |||
6003 | } | |||
6004 | ||||
6005 | ||||
6006 | wg_aip = &wg_peer->p_aips[0]; | |||
6007 | for (j = 0; j < wg_peer->p_aips_count; j++) { | |||
6008 | inet_ntop(wg_aip->a_af, &wg_aip->a_addr, | |||
6009 | hbuf, sizeof(hbuf)); | |||
6010 | printf("\t\twgaip %s/%d\n", hbuf, wg_aip->a_cidr); | |||
6011 | wg_aip++; | |||
6012 | } | |||
6013 | wg_peer = (struct wg_peer_io *)wg_aip; | |||
6014 | } | |||
6015 | } | |||
6016 | out: | |||
6017 | free(wgdata.wgd_interface); | |||
6018 | } | |||
6019 | ||||
6020 | const struct umb_valdescr umb_regstate[] = MBIM_REGSTATE_DESCRIPTIONS{ { 0, "unknown" }, { 1, "not registered" }, { 2, "searching" }, { 3, "home network" }, { 4, "roaming network" }, { 5, "partner network" }, { 6, "access denied" }, { 0, ((void *)0) } }; | |||
6021 | const struct umb_valdescr umb_dataclass[] = MBIM_DATACLASS_DESCRIPTIONS{ { 0x00000000, "none" }, { 0x00000001, "GPRS" }, { 0x00000002 , "EDGE" }, { 0x00000004, "UMTS" }, { 0x00000008, "HSDPA" }, { 0x00000010, "HSUPA" }, { 0x00000008|0x00000010, "HSPA" }, { 0x00000020 , "LTE" }, { 0x00010000, "CDMA2000" }, { 0x00020000, "CDMA2000" }, { 0x00040000, "CDMA2000" }, { 0x00080000, "CDMA2000" }, { 0x00100000, "CDMA2000" }, { 0x00200000, "CDMA2000" }, { 0x00400000 , "CDMA2000" }, { 0x80000000, "custom" }, { 0, ((void *)0) } }; | |||
6022 | const struct umb_valdescr umb_simstate[] = MBIM_SIMSTATE_DESCRIPTIONS{ { 0, "not initialized" }, { 1, "initialized" }, { 2, "not inserted" }, { 3, "bad type" }, { 4, "failed" }, { 5, "not activated" } , { 6, "locked" }, { 0, ((void *)0) } }; | |||
6023 | const struct umb_valdescr umb_istate[] = UMB_INTERNAL_STATE_DESCRIPTIONS{ { UMB_S_DOWN, "down" }, { UMB_S_OPEN, "open" }, { UMB_S_CID , "CID allocated" }, { UMB_S_RADIO, "radio on" }, { UMB_S_SIMREADY , "SIM is ready" }, { UMB_S_ATTACHED, "attached" }, { UMB_S_CONNECTED , "connected" }, { UMB_S_UP, "up" }, { 0, ((void *)0) } }; | |||
6024 | ||||
6025 | const struct umb_valdescr umb_classalias[] = { | |||
6026 | { MBIM_DATACLASS_GPRS0x00000001 | MBIM_DATACLASS_EDGE0x00000002, "2g" }, | |||
6027 | { MBIM_DATACLASS_UMTS0x00000004 | MBIM_DATACLASS_HSDPA0x00000008 | MBIM_DATACLASS_HSUPA0x00000010, | |||
6028 | "3g" }, | |||
6029 | { MBIM_DATACLASS_LTE0x00000020, "4g" }, | |||
6030 | { 0, NULL((void *)0) } | |||
6031 | }; | |||
6032 | ||||
6033 | static int | |||
6034 | umb_descr2val(const struct umb_valdescr *vdp, char *str) | |||
6035 | { | |||
6036 | while (vdp->descr != NULL((void *)0)) { | |||
6037 | if (!strcasecmp(vdp->descr, str)) | |||
6038 | return vdp->val; | |||
6039 | vdp++; | |||
6040 | } | |||
6041 | return 0; | |||
6042 | } | |||
6043 | ||||
6044 | void | |||
6045 | umb_status(void) | |||
6046 | { | |||
6047 | struct umb_info mi; | |||
6048 | char provider[UMB_PROVIDERNAME_MAXLEN20+1]; | |||
6049 | char providerid[UMB_PROVIDERID_MAXLEN20+1]; | |||
6050 | char roamingtxt[UMB_ROAMINGTEXT_MAXLEN63+1]; | |||
6051 | char devid[UMB_DEVID_MAXLEN18+1]; | |||
6052 | char fwinfo[UMB_FWINFO_MAXLEN30+1]; | |||
6053 | char hwinfo[UMB_HWINFO_MAXLEN30+1]; | |||
6054 | char sid[UMB_SUBSCRIBERID_MAXLEN15+1]; | |||
6055 | char iccid[UMB_ICCID_MAXLEN20+1]; | |||
6056 | char apn[UMB_APN_MAXLEN100+1]; | |||
6057 | char pn[UMB_PHONENR_MAXLEN22+1]; | |||
6058 | int i, n; | |||
6059 | char astr[INET6_ADDRSTRLEN46]; | |||
6060 | ||||
6061 | memset((char *)&mi, 0, sizeof(mi)); | |||
6062 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&mi; | |||
6063 | if (ioctl(sock, SIOCGUMBINFO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((190))), (caddr_t)&ifr) == -1) | |||
6064 | return; | |||
6065 | ||||
6066 | if (mi.nwerror) { | |||
6067 | /* 3GPP 24.008 Cause Code */ | |||
6068 | printf("\terror: "); | |||
6069 | switch (mi.nwerror) { | |||
6070 | case 2: | |||
6071 | printf("SIM not activated"); | |||
6072 | break; | |||
6073 | case 4: | |||
6074 | printf("Roaming not supported"); | |||
6075 | break; | |||
6076 | case 6: | |||
6077 | printf("SIM reported stolen"); | |||
6078 | break; | |||
6079 | case 7: | |||
6080 | printf("No GPRS subscription"); | |||
6081 | break; | |||
6082 | case 8: | |||
6083 | printf("GPRS and non-GPRS services not allowed"); | |||
6084 | break; | |||
6085 | case 11: | |||
6086 | printf("Subscription expired"); | |||
6087 | break; | |||
6088 | case 12: | |||
6089 | printf("Subscription does not cover current location"); | |||
6090 | break; | |||
6091 | case 13: | |||
6092 | printf("No roaming in this location"); | |||
6093 | break; | |||
6094 | case 14: | |||
6095 | printf("GPRS not supported"); | |||
6096 | break; | |||
6097 | case 15: | |||
6098 | printf("No subscription for the service"); | |||
6099 | break; | |||
6100 | case 17: | |||
6101 | printf("Registration failed"); | |||
6102 | break; | |||
6103 | case 22: | |||
6104 | printf("Network congestion"); | |||
6105 | break; | |||
6106 | default: | |||
6107 | printf("Error code %d", mi.nwerror); | |||
6108 | break; | |||
6109 | } | |||
6110 | printf("\n"); | |||
6111 | } | |||
6112 | ||||
6113 | printf("\troaming %s registration %s", | |||
6114 | mi.enable_roaming ? "enabled" : "disabled", | |||
6115 | umb_val2descr(umb_regstate, mi.regstate)); | |||
6116 | utf16_to_char(mi.roamingtxt, UMB_ROAMINGTEXT_MAXLEN63, | |||
6117 | roamingtxt, sizeof (roamingtxt)); | |||
6118 | if (roamingtxt[0]) | |||
6119 | printf(" [%s]", roamingtxt); | |||
6120 | printf("\n"); | |||
6121 | ||||
6122 | if (showclasses) | |||
6123 | umb_printclasses("available classes", mi.supportedclasses); | |||
6124 | printf("\tstate %s cell-class %s", | |||
6125 | umb_val2descr(umb_istate, mi.state), | |||
6126 | umb_val2descr(umb_dataclass, mi.highestclass)); | |||
6127 | if (mi.rssi != UMB_VALUE_UNKNOWN-999 && mi.rssi != 0) | |||
6128 | printf(" rssi %ddBm", mi.rssi); | |||
6129 | if (mi.uplink_speed != 0 || mi.downlink_speed != 0) { | |||
6130 | char s[2][FMT_SCALED_STRSIZE7]; | |||
6131 | if (fmt_scaled(mi.uplink_speed, s[0]) != 0) | |||
6132 | snprintf(s[0], sizeof (s[0]), "%llu", mi.uplink_speed); | |||
6133 | if (fmt_scaled(mi.downlink_speed, s[1]) != 0) | |||
6134 | snprintf(s[1], sizeof (s[1]), "%llu", mi.downlink_speed); | |||
6135 | printf(" speed %sbps up %sbps down", s[0], s[1]); | |||
6136 | } | |||
6137 | printf("\n"); | |||
6138 | ||||
6139 | printf("\tSIM %s PIN ", umb_val2descr(umb_simstate, mi.sim_state)); | |||
6140 | switch (mi.pin_state) { | |||
6141 | case UMB_PIN_REQUIRED0: | |||
6142 | printf("required"); | |||
6143 | break; | |||
6144 | case UMB_PIN_UNLOCKED1: | |||
6145 | printf("valid"); | |||
6146 | break; | |||
6147 | case UMB_PUK_REQUIRED2: | |||
6148 | printf("locked (PUK required)"); | |||
6149 | break; | |||
6150 | default: | |||
6151 | printf("unknown state (%d)", mi.pin_state); | |||
6152 | break; | |||
6153 | } | |||
6154 | if (mi.pin_attempts_left != UMB_VALUE_UNKNOWN-999) | |||
6155 | printf(" (%d attempts left)", mi.pin_attempts_left); | |||
6156 | printf("\n"); | |||
6157 | ||||
6158 | utf16_to_char(mi.sid, UMB_SUBSCRIBERID_MAXLEN15, sid, sizeof (sid)); | |||
6159 | utf16_to_char(mi.iccid, UMB_ICCID_MAXLEN20, iccid, sizeof (iccid)); | |||
6160 | utf16_to_char(mi.provider, UMB_PROVIDERNAME_MAXLEN20, | |||
6161 | provider, sizeof (provider)); | |||
6162 | utf16_to_char(mi.providerid, UMB_PROVIDERID_MAXLEN20, | |||
6163 | providerid, sizeof (providerid)); | |||
6164 | if (sid[0] || iccid[0]) { | |||
6165 | printf("\t"); | |||
6166 | n = 0; | |||
6167 | if (sid[0]) | |||
6168 | printf("%ssubscriber-id %s", n++ ? " " : "", sid); | |||
6169 | if (iccid[0]) | |||
6170 | printf("%sICC-id %s", n++ ? " " : "", iccid); | |||
6171 | printf("\n"); | |||
6172 | } | |||
6173 | ||||
6174 | utf16_to_char(mi.hwinfo, UMB_HWINFO_MAXLEN30, hwinfo, sizeof (hwinfo)); | |||
6175 | utf16_to_char(mi.devid, UMB_DEVID_MAXLEN18, devid, sizeof (devid)); | |||
6176 | utf16_to_char(mi.fwinfo, UMB_FWINFO_MAXLEN30, fwinfo, sizeof (fwinfo)); | |||
6177 | if (hwinfo[0] || devid[0] || fwinfo[0]) { | |||
6178 | printf("\t"); | |||
6179 | n = 0; | |||
6180 | if (hwinfo[0]) | |||
6181 | printf("%sdevice %s", n++ ? " " : "", hwinfo); | |||
6182 | if (devid[0]) { | |||
6183 | printf("%s", n++ ? " " : ""); | |||
6184 | switch (mi.cellclass) { | |||
6185 | case MBIM_CELLCLASS_GSM0x00000001: | |||
6186 | printf("IMEI"); | |||
6187 | break; | |||
6188 | case MBIM_CELLCLASS_CDMA0x00000002: | |||
6189 | n = strlen(devid); | |||
6190 | if (n == 8 || n == 11) { | |||
6191 | printf("ESN"); | |||
6192 | break; | |||
6193 | } else if (n == 14 || n == 18) { | |||
6194 | printf("MEID"); | |||
6195 | break; | |||
6196 | } | |||
6197 | /*FALLTHROUGH*/ | |||
6198 | default: | |||
6199 | printf("ID"); | |||
6200 | break; | |||
6201 | } | |||
6202 | printf(" %s", devid); | |||
6203 | } | |||
6204 | if (fwinfo[0]) | |||
6205 | printf("%sfirmware %s", n++ ? " " : "", fwinfo); | |||
6206 | printf("\n"); | |||
6207 | } | |||
6208 | ||||
6209 | utf16_to_char(mi.pn, UMB_PHONENR_MAXLEN22, pn, sizeof (pn)); | |||
6210 | utf16_to_char(mi.apn, UMB_APN_MAXLEN100, apn, sizeof (apn)); | |||
6211 | if (pn[0] || apn[0] || provider[0] || providerid[0]) { | |||
6212 | printf("\t"); | |||
6213 | n = 0; | |||
6214 | if (pn[0]) | |||
6215 | printf("%sphone# %s", n++ ? " " : "", pn); | |||
6216 | if (apn[0]) | |||
6217 | printf("%sAPN %s", n++ ? " " : "", apn); | |||
6218 | if (provider[0]) | |||
6219 | printf("%sprovider %s", n++ ? " " : "", provider); | |||
6220 | if (providerid[0]) | |||
6221 | printf("%sprovider-id %s", n ? " " : "", providerid); | |||
6222 | printf("\n"); | |||
6223 | } | |||
6224 | ||||
6225 | for (i = 0, n = 0; i < UMB_MAX_DNSSRV2; i++) { | |||
6226 | if (mi.ipv4dns[i].s_addr == INADDR_ANY((u_int32_t)(0x00000000))) | |||
6227 | break; | |||
6228 | printf("%s %s", n++ ? "" : "\tdns", | |||
6229 | inet_ntop(AF_INET2, &mi.ipv4dns[i], astr, sizeof(astr))); | |||
6230 | } | |||
6231 | for (i = 0; i < UMB_MAX_DNSSRV2; i++) { | |||
6232 | if (memcmp(&mi.ipv6dns[i], &in6addr_any, | |||
6233 | sizeof (mi.ipv6dns[i])) == 0) | |||
6234 | break; | |||
6235 | printf("%s %s", n++ ? "" : "\tdns", | |||
6236 | inet_ntop(AF_INET624, &mi.ipv6dns[i], astr, sizeof(astr))); | |||
6237 | } | |||
6238 | if (n) | |||
6239 | printf("\n"); | |||
6240 | } | |||
6241 | ||||
6242 | void | |||
6243 | umb_printclasses(char *tag, int c) | |||
6244 | { | |||
6245 | int i; | |||
6246 | char *sep = ""; | |||
6247 | ||||
6248 | printf("\t%s: ", tag); | |||
6249 | i = 0; | |||
6250 | while (umb_dataclass[i].descr) { | |||
6251 | if (umb_dataclass[i].val & c) { | |||
6252 | printf("%s%s", sep, umb_dataclass[i].descr); | |||
6253 | sep = ","; | |||
6254 | } | |||
6255 | i++; | |||
6256 | } | |||
6257 | printf("\n"); | |||
6258 | } | |||
6259 | ||||
6260 | int | |||
6261 | umb_parse_classes(const char *spec) | |||
6262 | { | |||
6263 | char *optlist, *str; | |||
6264 | int c = 0, v; | |||
6265 | ||||
6266 | if ((optlist = strdup(spec)) == NULL((void *)0)) | |||
6267 | err(1, "strdup"); | |||
6268 | str = strtok(optlist, ","); | |||
6269 | while (str != NULL((void *)0)) { | |||
6270 | if ((v = umb_descr2val(umb_dataclass, str)) != 0 || | |||
6271 | (v = umb_descr2val(umb_classalias, str)) != 0) | |||
6272 | c |= v; | |||
6273 | str = strtok(NULL((void *)0), ","); | |||
6274 | } | |||
6275 | free(optlist); | |||
6276 | return c; | |||
6277 | } | |||
6278 | ||||
6279 | void | |||
6280 | umb_setpin(const char *pin, int d) | |||
6281 | { | |||
6282 | umb_pinop(MBIM_PIN_OP_ENTER0, 0, pin, NULL((void *)0)); | |||
6283 | } | |||
6284 | ||||
6285 | void | |||
6286 | umb_chgpin(const char *pin, const char *newpin) | |||
6287 | { | |||
6288 | umb_pinop(MBIM_PIN_OP_CHANGE3, 0, pin, newpin); | |||
6289 | } | |||
6290 | ||||
6291 | void | |||
6292 | umb_puk(const char *pin, const char *newpin) | |||
6293 | { | |||
6294 | umb_pinop(MBIM_PIN_OP_ENTER0, 1, pin, newpin); | |||
6295 | } | |||
6296 | ||||
6297 | void | |||
6298 | umb_pinop(int op, int is_puk, const char *pin, const char *newpin) | |||
6299 | { | |||
6300 | struct umb_parameter mp; | |||
6301 | ||||
6302 | memset(&mp, 0, sizeof (mp)); | |||
6303 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)∓ | |||
6304 | if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((192))), (caddr_t)&ifr) == -1) | |||
6305 | err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); | |||
6306 | ||||
6307 | mp.op = op; | |||
6308 | mp.is_puk = is_puk; | |||
6309 | if ((mp.pinlen = char_to_utf16(pin, (uint16_t *)mp.pin, | |||
6310 | sizeof (mp.pin))) == -1) | |||
6311 | errx(1, "PIN too long"); | |||
6312 | ||||
6313 | if (newpin) { | |||
6314 | if ((mp.newpinlen = char_to_utf16(newpin, (uint16_t *)mp.newpin, | |||
6315 | sizeof (mp.newpin))) == -1) | |||
6316 | errx(1, "new PIN too long"); | |||
6317 | } | |||
6318 | ||||
6319 | if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((191))), (caddr_t)&ifr) == -1) | |||
6320 | err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); | |||
6321 | } | |||
6322 | ||||
6323 | void | |||
6324 | umb_apn(const char *apn, int d) | |||
6325 | { | |||
6326 | struct umb_parameter mp; | |||
6327 | ||||
6328 | memset(&mp, 0, sizeof (mp)); | |||
6329 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)∓ | |||
6330 | if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((192))), (caddr_t)&ifr) == -1) | |||
6331 | err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); | |||
6332 | ||||
6333 | if (d != 0) | |||
6334 | memset(mp.apn, 0, sizeof (mp.apn)); | |||
6335 | else if ((mp.apnlen = char_to_utf16(apn, mp.apn, | |||
6336 | sizeof (mp.apn))) == -1) | |||
6337 | errx(1, "APN too long"); | |||
6338 | ||||
6339 | if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((191))), (caddr_t)&ifr) == -1) | |||
6340 | err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); | |||
6341 | } | |||
6342 | ||||
6343 | void | |||
6344 | umb_setclass(const char *val, int d) | |||
6345 | { | |||
6346 | struct umb_parameter mp; | |||
6347 | ||||
6348 | if (val == NULL((void *)0)) { | |||
6349 | if (showclasses) | |||
6350 | usage(); | |||
6351 | showclasses = 1; | |||
6352 | return; | |||
6353 | } | |||
6354 | ||||
6355 | memset(&mp, 0, sizeof (mp)); | |||
6356 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)∓ | |||
6357 | if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((192))), (caddr_t)&ifr) == -1) | |||
6358 | err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); | |||
6359 | if (d != -1) | |||
6360 | mp.preferredclasses = umb_parse_classes(val); | |||
6361 | else | |||
6362 | mp.preferredclasses = MBIM_DATACLASS_NONE0x00000000; | |||
6363 | if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((191))), (caddr_t)&ifr) == -1) | |||
6364 | err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); | |||
6365 | } | |||
6366 | ||||
6367 | void | |||
6368 | umb_roaming(const char *val, int d) | |||
6369 | { | |||
6370 | struct umb_parameter mp; | |||
6371 | ||||
6372 | memset(&mp, 0, sizeof (mp)); | |||
6373 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)∓ | |||
6374 | if (ioctl(sock, SIOCGUMBPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((192))), (caddr_t)&ifr) == -1) | |||
6375 | err(1, "%s: SIOCGUMBPARAM", ifr.ifr_name); | |||
6376 | mp.roaming = d; | |||
6377 | if (ioctl(sock, SIOCSUMBPARAM((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((191))), (caddr_t)&ifr) == -1) | |||
6378 | err(1, "%s: SIOCSUMBPARAM", ifr.ifr_name); | |||
6379 | } | |||
6380 | ||||
6381 | void | |||
6382 | utf16_to_char(uint16_t *in, int inlen, char *out, size_t outlen) | |||
6383 | { | |||
6384 | uint16_t c; | |||
6385 | ||||
6386 | while (outlen > 0) { | |||
6387 | c = inlen > 0 ? letoh16(*in)((__uint16_t)(*in)) : 0; | |||
6388 | if (c == 0 || --outlen == 0) { | |||
6389 | /* always NUL terminate result */ | |||
6390 | *out = '\0'; | |||
6391 | break; | |||
6392 | } | |||
6393 | *out++ = isascii(c) ? (char)c : '?'; | |||
6394 | in++; | |||
6395 | inlen--; | |||
6396 | } | |||
6397 | } | |||
6398 | ||||
6399 | int | |||
6400 | char_to_utf16(const char *in, uint16_t *out, size_t outlen) | |||
6401 | { | |||
6402 | int n = 0; | |||
6403 | uint16_t c; | |||
6404 | ||||
6405 | for (;;) { | |||
6406 | c = *in++; | |||
6407 | ||||
6408 | if (c == '\0') { | |||
6409 | /* | |||
6410 | * NUL termination is not required, but zero out the | |||
6411 | * residual buffer | |||
6412 | */ | |||
6413 | memset(out, 0, outlen); | |||
6414 | return n; | |||
6415 | } | |||
6416 | if (outlen < sizeof (*out)) | |||
6417 | return -1; | |||
6418 | ||||
6419 | *out++ = htole16(c)((__uint16_t)(c)); | |||
6420 | n += sizeof (*out); | |||
6421 | outlen -= sizeof (*out); | |||
6422 | } | |||
6423 | } | |||
6424 | ||||
6425 | #endif | |||
6426 | ||||
6427 | #define SIN(x)((struct sockaddr_in *) &(x)) ((struct sockaddr_in *) &(x)) | |||
6428 | struct sockaddr_in *sintab[] = { | |||
6429 | SIN(ridreq.ifr_addr)((struct sockaddr_in *) &(ridreq.ifr_ifru.ifru_addr)), SIN(in_addreq.ifra_addr)((struct sockaddr_in *) &(in_addreq.ifra_ifrau.ifrau_addr )), | |||
6430 | SIN(in_addreq.ifra_mask)((struct sockaddr_in *) &(in_addreq.ifra_mask)), SIN(in_addreq.ifra_broadaddr)((struct sockaddr_in *) &(in_addreq.ifra_dstaddr))}; | |||
6431 | ||||
6432 | void | |||
6433 | in_getaddr(const char *s, int which) | |||
6434 | { | |||
6435 | struct sockaddr_in *sin = sintab[which], tsin; | |||
6436 | struct hostent *hp; | |||
6437 | int bits, l; | |||
6438 | char p[3]; | |||
6439 | ||||
6440 | bzero(&tsin, sizeof(tsin)); | |||
6441 | sin->sin_len = sizeof(*sin); | |||
6442 | if (which != MASK2) | |||
6443 | sin->sin_family = AF_INET2; | |||
6444 | ||||
6445 | if (which == ADDR1 && strrchr(s, '/') != NULL((void *)0) && | |||
6446 | (bits = inet_net_pton(AF_INET2, s, &tsin.sin_addr, | |||
6447 | sizeof(tsin.sin_addr))) != -1) { | |||
6448 | l = snprintf(p, sizeof(p), "%d", bits); | |||
6449 | if (l < 0 || l >= sizeof(p)) | |||
6450 | errx(1, "%d: bad prefixlen", bits); | |||
6451 | in_getprefix(p, MASK2); | |||
6452 | memcpy(&sin->sin_addr, &tsin.sin_addr, sizeof(sin->sin_addr)); | |||
6453 | } else if (inet_aton(s, &sin->sin_addr) == 0) { | |||
6454 | if ((hp = gethostbyname(s))) | |||
6455 | memcpy(&sin->sin_addr, hp->h_addrh_addr_list[0], hp->h_length); | |||
6456 | else | |||
6457 | errx(1, "%s: bad value", s); | |||
6458 | } | |||
6459 | if (which == MASK2 && (ntohl(sin->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(sin->sin_addr.s_addr) ? ( __uint32_t)(((__uint32_t)(sin->sin_addr.s_addr) & 0xff ) << 24 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff00 ) << 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff0000 ) >> 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff000000 ) >> 24) : __swap32md(sin->sin_addr.s_addr)) & | |||
6460 | (~ntohl(sin->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(sin->sin_addr.s_addr) ? ( __uint32_t)(((__uint32_t)(sin->sin_addr.s_addr) & 0xff ) << 24 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff00 ) << 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff0000 ) >> 8 | ((__uint32_t)(sin->sin_addr.s_addr) & 0xff000000 ) >> 24) : __swap32md(sin->sin_addr.s_addr)) >> 1))) | |||
6461 | errx(1, "%s: non-contiguous mask", s); | |||
6462 | } | |||
6463 | ||||
6464 | void | |||
6465 | in_getprefix(const char *plen, int which) | |||
6466 | { | |||
6467 | struct sockaddr_in *sin = sintab[which]; | |||
6468 | const char *errmsg = NULL((void *)0); | |||
6469 | u_char *cp; | |||
6470 | int len; | |||
6471 | ||||
6472 | len = strtonum(plen, 0, 32, &errmsg); | |||
6473 | if (errmsg) | |||
6474 | errx(1, "prefix %s: %s", plen, errmsg); | |||
6475 | ||||
6476 | sin->sin_len = sizeof(*sin); | |||
6477 | if (which != MASK2) | |||
6478 | sin->sin_family = AF_INET2; | |||
6479 | if ((len == 0) || (len == 32)) { | |||
6480 | memset(&sin->sin_addr, 0xff, sizeof(struct in_addr)); | |||
6481 | return; | |||
6482 | } | |||
6483 | memset((void *)&sin->sin_addr, 0x00, sizeof(sin->sin_addr)); | |||
6484 | for (cp = (u_char *)&sin->sin_addr; len > 7; len -= 8) | |||
6485 | *cp++ = 0xff; | |||
6486 | if (len) | |||
6487 | *cp = 0xff << (8 - len); | |||
6488 | } | |||
6489 | ||||
6490 | /* | |||
6491 | * Print a value a la the %b format of the kernel's printf | |||
6492 | */ | |||
6493 | void | |||
6494 | printb(char *s, unsigned int v, unsigned char *bits) | |||
6495 | { | |||
6496 | int i, any = 0; | |||
6497 | unsigned char c; | |||
6498 | ||||
6499 | if (bits && *bits == 8) | |||
6500 | printf("%s=%o", s, v); | |||
6501 | else | |||
6502 | printf("%s=%x", s, v); | |||
6503 | ||||
6504 | if (bits) { | |||
6505 | bits++; | |||
6506 | putchar('<')(!__isthreaded ? __sputc('<', (&__sF[1])) : (putc)('<' , (&__sF[1]))); | |||
6507 | while ((i = *bits++)) { | |||
6508 | if (v & (1 << (i-1))) { | |||
6509 | if (any) | |||
6510 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
6511 | any = 1; | |||
6512 | for (; (c = *bits) > 32; bits++) | |||
6513 | putchar(c)(!__isthreaded ? __sputc(c, (&__sF[1])) : (putc)(c, (& __sF[1]))); | |||
6514 | } else | |||
6515 | for (; *bits > 32; bits++) | |||
6516 | ; | |||
6517 | } | |||
6518 | putchar('>')(!__isthreaded ? __sputc('>', (&__sF[1])) : (putc)('>' , (&__sF[1]))); | |||
6519 | } | |||
6520 | } | |||
6521 | ||||
6522 | /* | |||
6523 | * A simple version of printb for status output | |||
6524 | */ | |||
6525 | void | |||
6526 | printb_status(unsigned short v, unsigned char *bits) | |||
6527 | { | |||
6528 | int i, any = 0; | |||
6529 | unsigned char c; | |||
6530 | ||||
6531 | if (bits) { | |||
6532 | bits++; | |||
6533 | while ((i = *bits++)) { | |||
6534 | if (v & (1 << (i-1))) { | |||
6535 | if (any) | |||
6536 | putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', ( &__sF[1]))); | |||
6537 | any = 1; | |||
6538 | for (; (c = *bits) > 32; bits++) | |||
6539 | putchar(tolower(c))(!__isthreaded ? __sputc(tolower(c), (&__sF[1])) : (putc) (tolower(c), (&__sF[1]))); | |||
6540 | } else | |||
6541 | for (; *bits > 32; bits++) | |||
6542 | ; | |||
6543 | } | |||
6544 | } | |||
6545 | } | |||
6546 | ||||
6547 | #define SIN6(x)((struct sockaddr_in6 *) &(x)) ((struct sockaddr_in6 *) &(x)) | |||
6548 | struct sockaddr_in6 *sin6tab[] = { | |||
6549 | SIN6(in6_ridreq.ifr_addr)((struct sockaddr_in6 *) &(in6_ridreq.ifr_ifru.ifru_addr) ), SIN6(in6_addreq.ifra_addr)((struct sockaddr_in6 *) &(in6_addreq.ifra_ifrau.ifrau_addr )), | |||
6550 | SIN6(in6_addreq.ifra_prefixmask)((struct sockaddr_in6 *) &(in6_addreq.ifra_prefixmask)), SIN6(in6_addreq.ifra_dstaddr)((struct sockaddr_in6 *) &(in6_addreq.ifra_dstaddr))}; | |||
6551 | ||||
6552 | void | |||
6553 | in6_getaddr(const char *s, int which) | |||
6554 | { | |||
6555 | struct sockaddr_in6 *sin6 = sin6tab[which]; | |||
6556 | struct addrinfo hints, *res; | |||
6557 | char buf[HOST_NAME_MAX255+1 + sizeof("/128")], *pfxlen; | |||
6558 | int error; | |||
6559 | ||||
6560 | memset(&hints, 0, sizeof(hints)); | |||
6561 | hints.ai_family = AF_INET624; | |||
6562 | hints.ai_socktype = SOCK_DGRAM2; /*dummy*/ | |||
6563 | ||||
6564 | if (which == ADDR1 && strchr(s, '/') != NULL((void *)0)) { | |||
6565 | if (strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) | |||
6566 | errx(1, "%s: bad value", s); | |||
6567 | pfxlen = strchr(buf, '/'); | |||
6568 | *pfxlen++ = '\0'; | |||
6569 | s = buf; | |||
6570 | in6_getprefix(pfxlen, MASK2); | |||
6571 | explicit_prefix = 1; | |||
6572 | } | |||
6573 | ||||
6574 | error = getaddrinfo(s, "0", &hints, &res); | |||
6575 | if (error) | |||
6576 | errx(1, "%s: %s", s, gai_strerror(error)); | |||
6577 | memcpy(sin6, res->ai_addr, res->ai_addrlen); | |||
6578 | #ifdef __KAME__ | |||
6579 | if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe ) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8 [1] & 0xc0) == 0x80)) && | |||
6580 | *(u_int16_t *)&sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] == 0 && | |||
6581 | sin6->sin6_scope_id) { | |||
6582 | *(u_int16_t *)&sin6->sin6_addr.s6_addr__u6_addr.__u6_addr8[2] = | |||
6583 | htons(sin6->sin6_scope_id & 0xffff)(__uint16_t)(__builtin_constant_p(sin6->sin6_scope_id & 0xffff) ? (__uint16_t)(((__uint16_t)(sin6->sin6_scope_id & 0xffff) & 0xffU) << 8 | ((__uint16_t)(sin6->sin6_scope_id & 0xffff) & 0xff00U) >> 8) : __swap16md(sin6-> sin6_scope_id & 0xffff)); | |||
6584 | sin6->sin6_scope_id = 0; | |||
6585 | } | |||
6586 | #endif /* __KAME__ */ | |||
6587 | freeaddrinfo(res); | |||
6588 | } | |||
6589 | ||||
6590 | void | |||
6591 | in6_getprefix(const char *plen, int which) | |||
6592 | { | |||
6593 | struct sockaddr_in6 *sin6 = sin6tab[which]; | |||
6594 | const char *errmsg = NULL((void *)0); | |||
6595 | u_char *cp; | |||
6596 | int len; | |||
6597 | ||||
6598 | len = strtonum(plen, 0, 128, &errmsg); | |||
6599 | if (errmsg) | |||
6600 | errx(1, "prefix %s: %s", plen, errmsg); | |||
6601 | ||||
6602 | sin6->sin6_len = sizeof(*sin6); | |||
6603 | if (which != MASK2) | |||
6604 | sin6->sin6_family = AF_INET624; | |||
6605 | if ((len == 0) || (len == 128)) { | |||
6606 | memset(&sin6->sin6_addr, 0xff, sizeof(struct in6_addr)); | |||
6607 | return; | |||
6608 | } | |||
6609 | memset((void *)&sin6->sin6_addr, 0x00, sizeof(sin6->sin6_addr)); | |||
6610 | for (cp = (u_char *)&sin6->sin6_addr; len > 7; len -= 8) | |||
6611 | *cp++ = 0xff; | |||
6612 | if (len) | |||
6613 | *cp = 0xff << (8 - len); | |||
6614 | } | |||
6615 | ||||
6616 | int | |||
6617 | prefix(void *val, int size) | |||
6618 | { | |||
6619 | u_char *nam = (u_char *)val; | |||
6620 | int byte, bit, plen = 0; | |||
6621 | ||||
6622 | for (byte = 0; byte < size; byte++, plen += 8) | |||
6623 | if (nam[byte] != 0xff) | |||
6624 | break; | |||
6625 | if (byte == size) | |||
6626 | return (plen); | |||
6627 | for (bit = 7; bit != 0; bit--, plen++) | |||
6628 | if (!(nam[byte] & (1 << bit))) | |||
6629 | break; | |||
6630 | for (; bit != 0; bit--) | |||
6631 | if (nam[byte] & (1 << bit)) | |||
6632 | return (0); | |||
6633 | byte++; | |||
6634 | for (; byte < size; byte++) | |||
6635 | if (nam[byte]) | |||
6636 | return (0); | |||
6637 | return (plen); | |||
6638 | } | |||
6639 | ||||
6640 | /* Print usage and exit */ | |||
6641 | __dead__attribute__((__noreturn__)) void | |||
6642 | usage(void) | |||
6643 | { | |||
6644 | fprintf(stderr(&__sF[2]), | |||
6645 | "usage: ifconfig [-AaC] [-M lladdr] [interface] [address_family]\n" | |||
6646 | "\t\t[address [dest_address]] [parameters]\n"); | |||
6647 | exit(1); | |||
6648 | } | |||
6649 | ||||
6650 | void | |||
6651 | getifgroups(void) | |||
6652 | { | |||
6653 | int len, cnt; | |||
6654 | struct ifgroupreq ifgr; | |||
6655 | struct ifg_req *ifg; | |||
6656 | ||||
6657 | memset(&ifgr, 0, sizeof(ifgr)); | |||
6658 | strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ16); | |||
6659 | ||||
6660 | if (ioctl(sock, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((136))), (caddr_t)&ifgr) == -1) { | |||
6661 | if (errno(*__errno()) == EINVAL22 || errno(*__errno()) == ENOTTY25) | |||
6662 | return; | |||
6663 | else | |||
6664 | err(1, "%s: SIOCGIFGROUP", ifgr.ifgr_name); | |||
6665 | } | |||
6666 | ||||
6667 | len = ifgr.ifgr_len; | |||
6668 | ifgr.ifgr_groupsifgr_ifgru.ifgru_groups = calloc(len / sizeof(struct ifg_req), | |||
6669 | sizeof(struct ifg_req)); | |||
6670 | if (ifgr.ifgr_groupsifgr_ifgru.ifgru_groups == NULL((void *)0)) | |||
6671 | err(1, "getifgroups"); | |||
6672 | if (ioctl(sock, SIOCGIFGROUP(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifgroupreq) & 0x1fff) << 16) | ((('i')) << 8) | ((136))), (caddr_t)&ifgr) == -1) | |||
6673 | err(1, "%s: SIOCGIFGROUP", ifgr.ifgr_name); | |||
6674 | ||||
6675 | cnt = 0; | |||
6676 | ifg = ifgr.ifgr_groupsifgr_ifgru.ifgru_groups; | |||
6677 | for (; ifg && len >= sizeof(struct ifg_req); ifg++) { | |||
6678 | len -= sizeof(struct ifg_req); | |||
6679 | if (strcmp(ifg->ifgrq_groupifgrq_ifgrqu.ifgrqu_group, "all")) { | |||
6680 | if (cnt == 0) | |||
6681 | printf("\tgroups:"); | |||
6682 | cnt++; | |||
6683 | printf(" %s", ifg->ifgrq_groupifgrq_ifgrqu.ifgrqu_group); | |||
6684 | } | |||
6685 | } | |||
6686 | if (cnt) | |||
6687 | printf("\n"); | |||
6688 | ||||
6689 | free(ifgr.ifgr_groupsifgr_ifgru.ifgru_groups); | |||
6690 | } | |||
6691 | ||||
6692 | #ifndef SMALL | |||
6693 | void | |||
6694 | printifhwfeatures(const char *unused, int show) | |||
6695 | { | |||
6696 | struct if_data ifrdat; | |||
6697 | ||||
6698 | if (!show) { | |||
6699 | if (showcapsflag) | |||
6700 | usage(); | |||
6701 | showcapsflag = 1; | |||
6702 | return; | |||
6703 | } | |||
6704 | bzero(&ifrdat, sizeof(ifrdat)); | |||
6705 | ifr.ifr_dataifr_ifru.ifru_data = (caddr_t)&ifrdat; | |||
6706 | if (ioctl(sock, SIOCGIFDATA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((27))), (caddr_t)&ifr) == -1) | |||
6707 | err(1, "%s: SIOCGIFDATA", ifr.ifr_name); | |||
6708 | printb("\thwfeatures", (u_int)ifrdat.ifi_capabilities, HWFEATURESBITS"\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6" "\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL"); | |||
6709 | ||||
6710 | if (ioctl(sock, SIOCGIFHARDMTU(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((165))), (caddr_t)&ifr) != -1) { | |||
6711 | if (ifr.ifr_hardmtuifr_ifru.ifru_metric) | |||
6712 | printf(" hardmtu %u", ifr.ifr_hardmtuifr_ifru.ifru_metric); | |||
6713 | } | |||
6714 | putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n', (&__sF[1]))); | |||
6715 | } | |||
6716 | #endif | |||
6717 | ||||
6718 | char * | |||
6719 | sec2str(time_t total) | |||
6720 | { | |||
6721 | static char result[256]; | |||
6722 | char *p = result; | |||
6723 | char *end = &result[sizeof(result)]; | |||
6724 | ||||
6725 | snprintf(p, end - p, "%lld", (long long)total); | |||
6726 | return (result); | |||
6727 | } | |||
6728 | ||||
6729 | void | |||
6730 | setiflladdr(const char *addr, int param) | |||
6731 | { | |||
6732 | struct ether_addr *eap, eabuf; | |||
6733 | ||||
6734 | if (!strcmp(addr, "random")) { | |||
6735 | arc4random_buf(&eabuf, sizeof eabuf); | |||
6736 | /* Non-multicast and claim it is a hardware address */ | |||
6737 | eabuf.ether_addr_octet[0] &= 0xfc; | |||
6738 | eap = &eabuf; | |||
6739 | } else { | |||
6740 | eap = ether_aton(addr); | |||
6741 | if (eap == NULL((void *)0)) { | |||
6742 | warnx("malformed link-level address"); | |||
6743 | return; | |||
6744 | } | |||
6745 | } | |||
6746 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
6747 | ifr.ifr_addrifr_ifru.ifru_addr.sa_len = ETHER_ADDR_LEN6; | |||
6748 | ifr.ifr_addrifr_ifru.ifru_addr.sa_family = AF_LINK18; | |||
6749 | bcopy(eap, ifr.ifr_addrifr_ifru.ifru_addr.sa_data, ETHER_ADDR_LEN6); | |||
6750 | if (ioctl(sock, SIOCSIFLLADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((31))), (caddr_t)&ifr) == -1) | |||
6751 | warn("SIOCSIFLLADDR"); | |||
6752 | } | |||
6753 | ||||
6754 | #ifndef SMALL | |||
6755 | void | |||
6756 | setrdomain(const char *id, int param) | |||
6757 | { | |||
6758 | const char *errmsg = NULL((void *)0); | |||
6759 | int rdomainid; | |||
6760 | ||||
6761 | rdomainid = strtonum(id, 0, RT_TABLEID_MAX255, &errmsg); | |||
6762 | if (errmsg) | |||
6763 | errx(1, "rdomain %s: %s", id, errmsg); | |||
6764 | ||||
6765 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
6766 | ifr.ifr_rdomainidifr_ifru.ifru_metric = rdomainid; | |||
6767 | if (ioctl(sock, SIOCSIFRDOMAIN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((159))), (caddr_t)&ifr) == -1) | |||
6768 | warn("SIOCSIFRDOMAIN"); | |||
6769 | } | |||
6770 | ||||
6771 | void | |||
6772 | unsetrdomain(const char *ignored, int alsoignored) | |||
6773 | { | |||
6774 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
6775 | ifr.ifr_rdomainidifr_ifru.ifru_metric = 0; | |||
6776 | if (ioctl(sock, SIOCSIFRDOMAIN((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((159))), (caddr_t)&ifr) == -1) | |||
6777 | warn("SIOCSIFRDOMAIN"); | |||
6778 | } | |||
6779 | #endif | |||
6780 | ||||
6781 | #ifndef SMALL | |||
6782 | void | |||
6783 | setpair(const char *val, int d) | |||
6784 | { | |||
6785 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
6786 | if ((ifr.ifr_indexifr_ifru.ifru_index = if_nametoindex(val)) == 0) { | |||
6787 | errno(*__errno()) = ENOENT2; | |||
6788 | err(1, "patch %s", val); | |||
6789 | } | |||
6790 | if (ioctl(sock, SIOCSIFPAIR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((176))), (caddr_t)&ifr) == -1) | |||
6791 | warn("SIOCSIFPAIR"); | |||
6792 | } | |||
6793 | ||||
6794 | void | |||
6795 | unsetpair(const char *val, int d) | |||
6796 | { | |||
6797 | ifr.ifr_indexifr_ifru.ifru_index = 0; | |||
6798 | strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); | |||
6799 | if (ioctl(sock, SIOCSIFPAIR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((176))), (caddr_t)&ifr) == -1) | |||
6800 | warn("SIOCSIFPAIR"); | |||
6801 | } | |||
6802 | #endif | |||
6803 | ||||
6804 | #ifdef SMALL | |||
6805 | void | |||
6806 | setignore(const char *id, int param) | |||
6807 | { | |||
6808 | /* just digest the command */ | |||
6809 | } | |||
6810 | #endif | |||
6811 | ||||
6812 | int | |||
6813 | findmac(const char *mac) | |||
6814 | { | |||
6815 | struct ifaddrs *ifap, *ifa; | |||
6816 | const char *ifnam = NULL((void *)0); | |||
6817 | struct if_clonereq *ifcr; | |||
6818 | int ret = 0; | |||
6819 | ||||
6820 | ifcr = get_cloners(); | |||
6821 | if (getifaddrs(&ifap) != 0) | |||
6822 | err(1, "getifaddrs"); | |||
6823 | ||||
6824 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | |||
6825 | struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr; | |||
6826 | ||||
6827 | if (sdl != NULL((void *)0) && sdl->sdl_alen && | |||
6828 | (sdl->sdl_type == IFT_ETHER0x06 || sdl->sdl_type == IFT_CARP0xf7)) { | |||
6829 | if (strcmp(ether_ntoa((struct ether_addr *)LLADDR(sdl)((caddr_t)((sdl)->sdl_data + (sdl)->sdl_nlen))), | |||
6830 | mac) == 0) { | |||
6831 | char *cp, *nam = ifa->ifa_name; | |||
6832 | int idx, skip = 0; | |||
6833 | size_t len; | |||
6834 | ||||
6835 | /* MACs on cloned devices are ignored */ | |||
6836 | for (len = 0; nam[len]; len++) | |||
6837 | if (isdigit((unsigned char)nam[len])) | |||
6838 | break; | |||
6839 | for (cp = ifcr->ifcr_buffer, idx = 0; | |||
6840 | idx < ifcr->ifcr_count; | |||
6841 | idx++, cp += IFNAMSIZ16) { | |||
6842 | if (strncmp(nam, cp, len) == 0) { | |||
6843 | skip = 1; | |||
6844 | break; | |||
6845 | } | |||
6846 | } | |||
6847 | if (skip) | |||
6848 | continue; | |||
6849 | ||||
6850 | if (ifnam) { /* same MAC on multiple ifp */ | |||
6851 | ret = 1; | |||
6852 | goto done; | |||
6853 | } | |||
6854 | ifnam = nam; | |||
6855 | } | |||
6856 | } | |||
6857 | } | |||
6858 | if (ifnam) | |||
6859 | printf("%s\n", ifnam); | |||
6860 | done: | |||
6861 | free(ifcr->ifcr_buffer); | |||
6862 | freeifaddrs(ifap); | |||
6863 | return ret; | |||
6864 | } |